在javafx表单上更新几个标签

时间:2021-01-22 17:00:01

There is simple application on JavaFx with SplitPane on Stage.
On SplitPane there are two StackPane. On Each there is one Label.
I want to update text on each Label's in cycle every per/sec. How can i do that in one Thread(one Task)? Is it real?

在舞台上使用SplitPane在JavaFx上有简单的应用程序。在SplitPane上有两个StackPane。每个都有一个标签。我希望每秒每秒更新每个Label的文本。我怎么能在一个线程(一个任务)中做到这一点?这是真的吗?

For example, i want to see text in labelUp = key of Map, and labelDw = value of Map.

例如,我想在Label的labelUp = key中看到文本,而labelDw = Map的值。

package com.javarush.test.MyTry;
import javafx.application.*;
import javafx.concurrent.Task;
import javafx.geometry.Orientation;
import javafx.scene.*;
import javafx.scene.control.Label;
import javafx.scene.control.SplitPane;
import javafx.stage.*;
import javafx.scene.layout.*;
import java.io.*;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Map;


public class Main extends Application
{

    Map<String, Integer> dictionary = new HashMap<>();

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

    public void init()
    {
        String filePath = "F:\\Java\\!Folder4Test\\test2.txt";
        try
        {
            BufferedReader reader = new BufferedReader(new FileReader(filePath));
            int cnt = 0;
            while (reader.ready())
            {
                String line = new String(reader.readLine().getBytes(), Charset.forName("UTF-8"));
                dictionary.put(line, cnt++);
            }
        }
        catch (FileNotFoundException e)
        {
            System.out.println("Не найден файл " + filePath);
            e.printStackTrace();
        }
        catch (IOException e)
        {
            System.out.println("Ошибка чтения файла " + filePath);
            e.printStackTrace();
        }
    }

    public void start(Stage myStage)
    {

        myStage.setTitle("JavaFXSkeleton.");
        SplitPane sp = new SplitPane();
        sp.setOrientation(Orientation.VERTICAL);
        Label labelUp = new Label("test");
        Label labelDw = new Label("тест");

        Scene scene = new Scene(sp, 800, 800);
        myStage.setScene(scene);

        final StackPane sp1 = new StackPane();
        sp1.getChildren().add(labelUp);
        final StackPane sp2 = new StackPane();
        sp2.getChildren().add(labelDw);

        sp.setOnMouseClicked(event -> {

            Task<Void> task = new Task<Void>()
            {
                @Override
                public Void call() throws Exception
                {
                    for (Map.Entry<String, Integer> pair : dictionary.entrySet())
                    {
                        updateMessage(pair.getKey());
                        System.out.println(pair.getKey());
                        Thread.sleep(250);
                    }
                    return null;
                }
            };
            task.messageProperty().addListener((obs, oldMessage, newMessage) -> labelUp.setText(newMessage));
            //there i want to update text on labelDw in same time
            //task.messageProperty().addListener((a1,a2,a3)->labelDw.setText());
            new Thread(task).start();

        });

        sp.getItems().addAll(sp1, sp2);
        sp.setDividerPositions(0.5f, 0.5f);


        myStage.show();
    }

    public void stop()
    {
        System.out.println("B теле метода stop().");
    }
}

(Sorry for my bad English)

(对不起,我的英语不好)

1 个解决方案

#1


1  

Use the Animation API. E.g. using a timeline:

使用动画API。例如。使用时间表:

sp.setOnMouseClicked(event -> {

    Timeline timeline = new Timeline();
    int step = 250 ;
    int millis = 0 ;
    for (Map.Entry<String, Integer> entry : dictionary.entrySet()) {
        timeline.getKeyFrames().add(new KeyFrame(Duration.millis(millis), e -> {
            labelUp.setText(entry.getKey());
            labelDw.setText(entry.getValue().toString());
        }));
        millis += step ;
    }
    timeline.play();
});

If you want to use a thread, you can do so with:

如果要使用线程,可以使用以下命令:

sp.setOnMouseClicked(event -> {

    Task<Void> task = new Task<Void>()
    {
        @Override
        public Void call() throws Exception
        {
            for (Map.Entry<String, Integer> pair : dictionary.entrySet())
            {
                Platform.runLater(() -> {
                    labelUp.setText(pair.getKey());
                    labelDw.setText(pair.getValue().toString());
                });
                System.out.println(pair.getKey());
                Thread.sleep(250);
            }
            return null;
        }
    };
    new Thread(task).start();

});

but I recommend using a timeline here.

但我建议在这里使用时间表。

#1


1  

Use the Animation API. E.g. using a timeline:

使用动画API。例如。使用时间表:

sp.setOnMouseClicked(event -> {

    Timeline timeline = new Timeline();
    int step = 250 ;
    int millis = 0 ;
    for (Map.Entry<String, Integer> entry : dictionary.entrySet()) {
        timeline.getKeyFrames().add(new KeyFrame(Duration.millis(millis), e -> {
            labelUp.setText(entry.getKey());
            labelDw.setText(entry.getValue().toString());
        }));
        millis += step ;
    }
    timeline.play();
});

If you want to use a thread, you can do so with:

如果要使用线程,可以使用以下命令:

sp.setOnMouseClicked(event -> {

    Task<Void> task = new Task<Void>()
    {
        @Override
        public Void call() throws Exception
        {
            for (Map.Entry<String, Integer> pair : dictionary.entrySet())
            {
                Platform.runLater(() -> {
                    labelUp.setText(pair.getKey());
                    labelDw.setText(pair.getValue().toString());
                });
                System.out.println(pair.getKey());
                Thread.sleep(250);
            }
            return null;
        }
    };
    new Thread(task).start();

});

but I recommend using a timeline here.

但我建议在这里使用时间表。