当前位置: 首页 > 知识库问答 >
问题:

不断更新JavaFXGUI

韦德厚
2023-03-14

我目前正在做一个项目,在这个项目中,我将时间转换为基数10时间(本质上,它最终会显示已经过去的一天的百分比。例如:中午12:00将显示为基数10时间的50.00)。目前,我知道我的算法是正确的,因为如果我把它打印到控制台,它会正确地打印出来,但是由于某种原因,我无法显示我的图形用户界面。如果我删除了试图不断更新GUI以显示正确数字的部分,GUI显示良好,但没有数字。我的代码如下:

package ClockPackage;

import java.util.Calendar;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.text.Text;
import javafx.stage.Stage;

public class ClockView extends Application {
    Pane background;
    static Text firstDigit;
    static Text secondDigit;
    static Text thirdDigit;
    static Text fourthDigit;
    Text middleDecimal;

    /* Sets the first digit of the base 10 time to the passed through char. */
    static void setFirstDigit(char x1) {
        String digitString = "";
        digitString += x1;
        firstDigit.setText(digitString);
    }

    /* Sets the second digit of the base 10 time to the passed through char. */
    static void setSecondDigit(char x2) {
        String digitString = "";
        digitString += x2;
        secondDigit.setText(digitString);
    }

    /* Sets the third digit of the base 10 time to the passed through char. */
    static void setThirdDigit(char y1) {
        String digitString = "";
        digitString += y1;
        thirdDigit.setText(digitString);
    }

    /* Sets the fourth digit of the base 10 time to the passed through char. */
    static void setFourthDigit(char y2) {
        String digitString = "";
        digitString += y2;
        fourthDigit.setText(digitString);
    }

    /* Main Method that Launches the GUI */
    public static void main(String[] args) {
        Application.launch(args);

    }

    @Override
    public void start(Stage primaryStage) throws Exception {
            final double TEXTFIELD_LAYOUT_Y = 200;

            //Background Pane
            background = new Pane();

            //First digit textField
            firstDigit = new Text();
            firstDigit.setLayoutX(17);
            firstDigit.setLayoutY(TEXTFIELD_LAYOUT_Y);
            firstDigit.setStyle("-fx-font-size: 96pt;");

            //Second digit textField
            secondDigit = new Text();
            secondDigit.setLayoutX(117);
            secondDigit.setLayoutY(TEXTFIELD_LAYOUT_Y);
            secondDigit.setStyle("-fx-font-size: 96pt;");

            //Middle decimal
            middleDecimal = new Text(".");
            middleDecimal.setLayoutX(219);
            middleDecimal.setLayoutY(210);
            middleDecimal.setStyle("-fx-font-size: 72pt;");

            //Third digit textField
            thirdDigit = new Text();
            thirdDigit.setLayoutX(250);
            thirdDigit.setLayoutY(TEXTFIELD_LAYOUT_Y);
            thirdDigit.setStyle("-fx-font-size: 96pt;");

            //Fourth digit textField
            fourthDigit = new Text();
            fourthDigit.setLayoutX(362);
            fourthDigit.setLayoutY(TEXTFIELD_LAYOUT_Y);
            fourthDigit.setStyle("-fx-font-size: 96pt;");

            /* Adding the Nodes to the Pane */
            background.getChildren().addAll(firstDigit, secondDigit, middleDecimal, thirdDigit, fourthDigit);

            /* Setting the Scene */
            Scene scene = new Scene(background, 470, 258);
            primaryStage.setTitle("Base 10 Clock");
            primaryStage.setScene(scene);
            primaryStage.show();

            /*
             * Calculates the time in base 10 time and calls the 4 methods
             * to set the GUI display.
             * 
             * In a constant while loop in order to continuously update
             * the GUI.
             */
            Calendar now;
            double currentTime;
            String timeString;
            long timestamp;
            while(true) {
                /* Sleep for 8.64 seconds since that is how long it is between
                increments of 0.01 in base 10 time. */
                Thread.sleep(8640);
                now = Calendar.getInstance();
                timestamp = now.get(Calendar.HOUR_OF_DAY)*60*60 + now.get(Calendar.MINUTE)*60 + now.get(Calendar.SECOND);
                currentTime = timestamp/86400.0;
                timeString = "" + currentTime;
                setFirstDigit(timeString.charAt(2));
                setSecondDigit(timeString.charAt(3));
                setThirdDigit(timeString.charAt(4));
                setFourthDigit(timeString.charAt(5));
            }
    }
}

有人知道我将如何让GUI显示并不断更新数字吗?我想不出如何让它同时做到这两个方面。我见过人们使用按钮更新数据的地方,但我没有见过显示器不断自动更新的地方。

谢谢

共有3个答案

华炜
2023-03-14

应该用新线程替换while(true)循环,或者用另一个线程替换服务调用。主线程已经负责更新UI,因此当您遇到某种阻塞(IO、耗时的循环等)时,它将阻止UI线程更新。

链接到服务接口

创建服务:

public static class TimeService extends Service<String> {

    protected Task createTask() {
        return new Task<String>() {
            protected String call() throws Exception {
                // TODO: Do work - return the date/time as a String
                // If you need a Thread.sleep, use a spawn a new thread
            }
        };
    }
}

然后在控制器中:

TimeService timeService = new TimeService();
timeService.restart();

您还可以做各种各样的事情,比如将用户界面元素绑定到TimeService中的属性(这样用户界面将在服务运行时“只是更新”)。

皇甫通
2023-03-14

这里是一个工作版本。

import java.util.Calendar;
import java.util.Timer;
import java.util.TimerTask;

import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.text.Text;
import javafx.stage.Stage;

public class ClockView extends Application {
    Pane background;
    static Text firstDigit;
    static Text secondDigit;
    static Text thirdDigit;
    static Text fourthDigit;
    Text middleDecimal;

    public final Timer clockTimer = new Timer();


    /* Sets the first digit of the base 10 time to the passed through char. */
    static void setFirstDigit(char x1) {
        String digitString = "";
        digitString += x1;
        firstDigit.setText(digitString);
    }

    /* Sets the second digit of the base 10 time to the passed through char. */
    static void setSecondDigit(char x2) {
        String digitString = "";
        digitString += x2;
        secondDigit.setText(digitString);
    }

    /* Sets the third digit of the base 10 time to the passed through char. */
    static void setThirdDigit(char y1) {
        String digitString = "";
        digitString += y1;
        thirdDigit.setText(digitString);
    }

    /* Sets the fourth digit of the base 10 time to the passed through char. */
    static void setFourthDigit(char y2) {
        String digitString = "";
        digitString += y2;
        fourthDigit.setText(digitString);
    }

    /* Main Method that Launches the GUI */
    public static void main(String[] args) {
        launch(args);
    }


    @Override
    public void start(Stage primaryStage) throws Exception {
        final double TEXTFIELD_LAYOUT_Y = 200;

        //Background Pane
        background = new Pane();

        //First digit textField
        firstDigit = new Text("0");
        firstDigit.setLayoutX(17);
        firstDigit.setLayoutY(TEXTFIELD_LAYOUT_Y);
        firstDigit.setStyle("-fx-font-size: 96pt;");

        //Second digit textField
        secondDigit = new Text("0");
        secondDigit.setLayoutX(117);
        secondDigit.setLayoutY(TEXTFIELD_LAYOUT_Y);
        secondDigit.setStyle("-fx-font-size: 96pt;");

        //Middle decimal
        middleDecimal = new Text(".");
        middleDecimal.setLayoutX(219);
        middleDecimal.setLayoutY(210);
        middleDecimal.setStyle("-fx-font-size: 72pt;");

        //Third digit textField
        thirdDigit = new Text("0");
        thirdDigit.setLayoutX(250);
        thirdDigit.setLayoutY(TEXTFIELD_LAYOUT_Y);
        thirdDigit.setStyle("-fx-font-size: 96pt;");

        //Fourth digit textField
        fourthDigit = new Text("0");
        fourthDigit.setLayoutX(362);
        fourthDigit.setLayoutY(TEXTFIELD_LAYOUT_Y);
        fourthDigit.setStyle("-fx-font-size: 96pt;");

        /* Adding the Nodes to the Pane */
        background.getChildren().addAll(firstDigit, secondDigit, middleDecimal, thirdDigit, fourthDigit);

        /* Setting the Scene */
        Scene scene = new Scene(new Group(), 470, 258);
        Group root = (Group)scene.getRoot();
        root.getChildren().add(background);
        primaryStage.setTitle("Base 10 Clock");
        primaryStage.setScene(scene);
        primaryStage.show();

        clockTimer.scheduleAtFixedRate(new TimerTask() {

                Calendar now;
                double currentTime;
                String timeString;
                long timestamp;

                @Override
                public void run() { 
                    /*
                     * Calculates the time in base 10 time and calls the 4 methods
                     * to set the GUI display.
                     * 
                     * In a constant while loop in order to continuously update
                     * the GUI.
                     */
                    now = Calendar.getInstance();
                    timestamp = now.get(Calendar.HOUR_OF_DAY)*60*60 + now.get(Calendar.MINUTE)*60 + now.get(Calendar.SECOND);
                    currentTime = timestamp/86400.0;
                    timeString = "" + currentTime;
                    Platform.runLater(new Runnable() {
                        @Override  public void run() {
                            setFirstDigit(timeString.charAt(2));
                            setSecondDigit(timeString.charAt(3));
                            setThirdDigit(timeString.charAt(4));
                            setFourthDigit(timeString.charAt(5));
                        }
                    });
                }
            }, 0, 8640  // Sleep for 8.64 seconds since that is how long it is between
        );              // increments of 0.01 in base 10 time.
    }
}
漆雕彦
2023-03-14

替换:

    Calendar now;
    double currentTime;
    String timeString;
    long timestamp;
    while (true)
    {
        /* Sleep for 8.64 seconds since that is how long it is between
            increments of 0.01 in base 10 time. */
        Thread.sleep(8640);
        now = Calendar.getInstance();
        timestamp = now.get(Calendar.HOUR_OF_DAY) * 60 * 60 + now.get(Calendar.MINUTE) * 60 + now.get(Calendar.SECOND);
        currentTime = timestamp / 86400.0;
        timeString = "" + currentTime;
        setFirstDigit(timeString.charAt(2));
        setSecondDigit(timeString.charAt(3));
        setThirdDigit(timeString.charAt(4));
        setFourthDigit(timeString.charAt(5));
    }

与:

        Timeline overEightSeconsWonder = new Timeline(new KeyFrame(Duration.seconds(8.64), (ActionEvent event) ->
        {
            Calendar now = Calendar.getInstance();
            long timestamp = now.get(Calendar.HOUR_OF_DAY) * 60 * 60 + now.get(Calendar.MINUTE) * 60 + now.get(Calendar.SECOND);
            double currentTime = timestamp / 86400.0;
            String timeString = "" + currentTime;
            setFirstDigit(timeString.charAt(2));
            setSecondDigit(timeString.charAt(3));
            setThirdDigit(timeString.charAt(4));
            setFourthDigit(timeString.charAt(5));
        }));
        overEightSeconsWonder.setCycleCount(Timeline.INDEFINITE);
        overEightSeconsWonder.play();
 类似资料:
  • 不确定是不是因为okhttp版本,但我尝试了2.3.0和3.4.0之间的几个不同版本,但都不起作用。 有什么想法吗?提前谢了。

  • 我在React本地项目上工作,在那里我获得了位置权限。此外,我必须跟踪位置的权限,总是像如果用户已经给了权限访问后,安装应用程序,然后在一段时间后,用户去设备设置中的应用程序设置和禁用/撤销权限。再次,一旦应用程序从后台到前台,我必须检查权限的基础上,需要显示的消息。 这怎么处理?有什么建议吗?

  • 由于 Vue 进行异步更新 DOM的情况,一些依赖 DOM 更新结果的断言必须在Vue.nextTick回调中进行: // 在状态更新后检查生成的 HTML it('updates the rendered message when vm.message updates', done => { const vm = new Vue(MyComponent).$mount() vm.mes

  • 我有一个日志文件,它不断更新新的数据行。我需要在java中获得新添加的数据。目前我的解决方案是: 但我有一种感觉,应该有更好的方法。我不喜欢内部有“睡眠”的持续运行循环的想法,我更喜欢某种事件驱动的方法。 如果每次修改文件时都依赖文件系统事件重新打开文件,则会产生延迟。 在这种情况下,正确的做法是什么? 提前谢谢!

  • 我有一个大 gui 的 JList,我删除了所有其他不相关的代码。我可以初始化列表,但在使用按钮时无法从中添加/删除项目。我读到的所有内容都说要使用DefaultListModel。然后,当您重新初始化列表时,它将自动更新列表。 我也尝试重新聚焦并重新粉刷面板和框架,但这也不起作用。

  • 我找到了更新数据的示例,但它使用了DefaultTableModel。当我创建自己的TableModel和自己的data类时,当我将数据添加到JTable中时,它不会更新。 有我的桌子模型: 当我添加了任何信息,但它没有更新。在JTable中,我必须把这个方法放在哪里来进行正确的数据更新?