【问题标题】:Display text/shape at a specified time in JavaFX在 JavaFX 中的指定时间显示文本/形状
【发布时间】:2018-05-22 00:07:22
【问题描述】:

我遇到了 javaFX 的问题。 我想每 1000 毫秒在 App Window 中显示一次时间。

public class Main extends Application {

StackPane root = new StackPane();
Time time;
Text t1;
@Override
public void start(Stage primaryStage) throws Exception{
    root.setStyle("-fx-background-color: #00FF00");
    primaryStage.setTitle("My App");
    primaryStage.setScene(new Scene(root, 1000, 800));
    primaryStage.show();
    checkTime();


    primaryStage.setOnCloseRequest(new EventHandler<WindowEvent>() {
        @Override
        public void handle(WindowEvent t) {
            Platform.exit();
            System.exit(0);
        }
    });
}


public static void main(String[] args) {
    launch(args);
}

public void checkTime(){
    time = new Time();
    time.start();
}

public void displayTime(int hour, int minute, int second){
    t1= new Text(200, 50, hour + ":" + minute + ":" + second);
    root.getChildren().add(t1);
}


}

这是第二类:

package sample;


import java.util.Calendar;

public class Time extends Thread {

Thread t;
public int hour;
public int minute;
public int second;
Calendar calendar;
Main main = new Main();


Time() {
}

public void run() {
    for (; ; ) {
        try {
            getTime();
            Thread.sleep(1000);
        } catch (InterruptedException e) {
        }
    }
}

public void start() {
    t = new Thread(this);
    t.start();

}

public void getTime() {
    calendar = Calendar.getInstance();
    hour = calendar.get(Calendar.HOUR);
    minute = calendar.get(Calendar.MINUTE);
    second = calendar.get(Calendar.SECOND);
    System.out.println(hour + ":" + minute + ":" + second);
    main.displayTime(hour, minute, second);

}


}

我希望它以类似于数字时钟的方式工作。在项目的下一个阶段,我将希望以类似于其他 2D 人物的方式使用这种方式。

此时,打开应用程序后,在控制台花费的时间是正确的。但是,我希望在应用程序窗口中显示完全相同的时间,此时只显示背景,不显示其他内容。

【问题讨论】:

    标签: java javafx javafx-8


    【解决方案1】:
    1. 大多数情况下,您不需要直接从Thread 扩展,因为JavaFX 有类似Timeline 的东西可以充当计时器。如果您认为有必要(由于您未指定的其他原因),拥有 Time 类是完全可以的。
    2. Thread 扩展并创建另一个Thread 绝对没有必要。当Time 类扩展Thread 时,它本身已经是Thread
    3. 您正在Time 中创建Main 的新实例。 Main 应该创建 Time 并将其自身传递给 Time,否则 Time 将不会持有原始 Main 对象的引用。
    4. 我认为即使您解决了#3,您也肯定会在运行时遇到一些异常。您正在通过非 JavaFX 应用程序线程(即您的 Time 类线程)直接修改场景图。此外,每个Time 循环都会创建一个新的Text 对象,因此即使没有异常,这些Text 对象也会相互重叠。

    如果您出于其他特殊原因想要保留Time 类,那么这通常是您应该做的:

    public class Main extends Application {
        StackPane root = new StackPane();
        Time time;
        Text t1 = new Text(); // Instantiates only once
    
        @Override
        public void start(Stage primaryStage) throws Exception{
            root.setStyle("-fx-background-color: #00FF00");
            primaryStage.setTitle("My App");
            primaryStage.setScene(new Scene(root, 1000, 800));
            primaryStage.show();
    
            root.getChildren().add(t1);
    
            checkTime();
    
    
            primaryStage.setOnCloseRequest(new EventHandler<WindowEvent>() {
                @Override
                public void handle(WindowEvent t) {
                    Platform.exit();
                    System.exit(0);
                }
            });
        }
    
    
        public static void main(String[] args) {
            launch(args);
        }
    
        public void checkTime(){
            time = new Time(this); // Pass ownself into Time
            time.start();
        }
    
        public void updateTime(int hour, int minute, int second){
            Platform.runLater(() -> t1.setText(200, 50, hour + ":" + minute + ":" + second));
        }
    }
    
    public class Time extends Thread {
        //Thread t; // Not needed
        public int hour;
        public int minute;
        public int second;
        Calendar calendar;
        Main main; // Don't instantiate
    
        // Pass in the main object
        Time(Main main) {
            this.main = main;
        }
    
        public void run() {
            for (; ; ) {
                try {
                    getTime();
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                }
            }
        }
    
        // This is not needed, Time class has its own start() method, which will call its run() method.
        //public void start() {
        //    t = new Thread(this);
        //    t.start();
        //}
    
        public void getTime() {
            calendar = Calendar.getInstance();
            hour = calendar.get(Calendar.HOUR);
            minute = calendar.get(Calendar.MINUTE);
            second = calendar.get(Calendar.SECOND);
            System.out.println(hour + ":" + minute + ":" + second);
            main.updateTime(hour, minute, second); // Update main
        }
    }
    

    【讨论】:

    • 可能更好的关闭应用程序的方法(即从代码中调用Stage.close 时也可以使用的方法)是使用守护线程:将setDaemon(true); 添加到Time 构造函数和删除 onCloseRequest 处理程序。此外,Time 类应根据信息隐藏原则稍作改写:所有字段都应为private(或转换为局部变量),getTime 方法也不应为public。也可以将main 字段设为finalMain.checkTime 也不应该公开...
    • @fabian 是的,OP给出的代码有很多问题(有些是次要的),我主要指出那些实际上会影响整个事情是否会工作的问题......好吧,除了#2,我觉得很烦,我需要说出来;D
    猜你喜欢
    • 1970-01-01
    • 2018-12-03
    • 1970-01-01
    • 1970-01-01
    • 2020-03-28
    • 2017-07-01
    • 1970-01-01
    • 2020-09-14
    • 1970-01-01
    相关资源
    最近更新 更多