繁体   English   中英

在线程中刷新Java FX窗口

[英]Refreshing Java FX window in thread

我有客户端-服务器应用程序,客户端有两个线程,一个线程用于向服务器发送信息,另一个线程应显示变化的窗口,但出现错误。 我已经阅读了有关Platform.runlater的内容,但我不知道如何使用它。 这是带有窗口的课程:

import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.stage.Stage;

public class B implements Runnable{

private int counter = 0, lg;
private double x_1, x_2, y_1, y_2;
int [] bts = new int[2];
Button[] change_bts = new Button[2];
Button [] all_bts = new Button[221];

public void run() {

    Group grupa = new Group();
    int x = 0; 

    int ctr = 1;


    for (int i = 0; i < 17; ++i) {
        for (int j = 0; j < 13; ++j) {
            if ( i%2 == 1)  {  x = 30; }
            else { x = 0; }

            Button bt = new Button();
            bt.setLayoutX(x+30+j*60); bt.setLayoutY(30+i*60);

            bt.setOnAction(
                    event -> { 
                        if((bt.getText()!="0")) {
                            if ((counter == 1)) {
                                change_bts[counter] = bt;
                                bts[0] = Integer.parseInt(change_bts[0].getText());
                                bts[1] = Integer.parseInt(change_bts[1].getText());
                            }
                            else if (counter == 0) {
                                change_bts[counter] = bt;
                                counter++;
                            }
                        }
                        System.out.println(bt.getText());
                    }
            );
            all_bts[ctr-1] =  bt;
            ctr ++;
        }
    }
    grupa.getChildren().addAll(all_bts);
    Scene tsc = new Scene(grupa, 1100, 1200);
    Stage tst = new Stage(); //New window (Stage)
    tst.setScene(tsc);
    tst.show();
}
}

这是创建新线程的类:

import javafx.application.Application;
import javafx.stage.Stage;
import java.io.IOException;

public class Clients extends Application {

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

public void start(final Stage first_stage) throws IOException, InterruptedException {
   Names n = new Names (); // this Class' constructor calls gogo() method below
}
public static void gogo(String a) {
    Runnable[] runners = new Runnable[2];
    Thread[] threads = new Thread[2];

        runners[0] = new B();
        runners[1] = new Another_Class();

        threads[0] = new Thread(runners[0]);
        threads[1] = new Thread(runners[1]);

        threads[0].start();
        threads[1].start();
}
}

请帮助:<

正如@Eggplant正确指出的那样,不允许Thread类对象操纵JavaFx UI组件,并且必须使用JavaFx线程操纵所有UI组件。 Platform.runLater的作用是在运行的JavaFx线程中安排UI更改。 像这样使用它:

Platform.runLater(() -> {
//your UI manipulation code here...
});

您实际上可以使用其他“线程”实例中的这段代码来将UI操作委派给实际的JavaFx线程。

考虑将客户端所需的信息封装在单独的类(通常称为模型)中。
客户(视图)应响应模型中的更改。 在以下示例中,它是通过绑定来完成的。
现在,您可以使用线程来更新模型:

import java.io.IOException;
import java.util.concurrent.TimeUnit;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;

public class Clients extends Application {

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

    @Override
    public void start(final Stage first_stage) throws IOException, InterruptedException {

        Model model = new Model();
        Button run = new Button("Run");
        run.setOnAction(e -> {
            gogo(model);
            run.setDisable(true);
        });

        Label counter = new Label();
        counter.textProperty().bind(model.getCounterProperty().asString());

        BorderPane root = new BorderPane(counter);
        root.setBottom(run);
        Scene scene = new Scene(root);
        first_stage.setScene(scene);
        first_stage.show();
    }

    private void gogo(Model model) {
        //thread manipulates model 
        new Thread(new Updater(model)).start();
    }
}

class Updater implements Runnable{

    private final Model model;
    private int counter = 0;
    private boolean stop = false;

    public Updater(Model model) {
        this.model = model;
    }

    @Override
    public void run() {
        while (! stop){
            model.setCounter(++counter);
            try {
                TimeUnit.MILLISECONDS.sleep(1000);
            } catch (InterruptedException ex) { ex.printStackTrace();}
        }
    }

    void setStop(boolean stop) {this.stop = stop;   }
}

//use a model to encapsulate information needed for the view 
class Model {

    private final SimpleIntegerProperty counterProperty = new SimpleIntegerProperty(0);

    SimpleIntegerProperty getCounterProperty() { return counterProperty; }

    //use `Platform.runLater` to allow update from non javafx thread 
    //if updated by more than one thread it needs to be synchronized 
    void setCounter(int value) {
        Platform.runLater(() -> counterProperty.set(value) );
    }
}

这是一个简单的示例,向您展示如何使用Platform.runLater(()-> ...); 我试图使其与您的应用程序相似,但我的功能被忽略了,我也在其中添加了一些评论

public class Main extends Application {

    @Override
    public void start(Stage stage) throws Exception{
        VBox vBox = new VBox();
        vBox.setAlignment(Pos.CENTER);

        for (int i = 0; i < 3; i++) {
            //Create new class with Runnable Implemented
            IncrementingButton button = new IncrementingButton();
            vBox.getChildren().add(button.getButton());
            //Start Thread
            new Thread(button).start();
        }

        stage  = new Stage();
        stage.setScene(new Scene(vBox, 100, 100));
        stage.setAlwaysOnTop(true);
        stage.show();
    }

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

    class IncrementingButton implements Runnable{

        int count = 0;
        private Button button = new Button();

        private Button getButton(){ return button; }

        @Override
        public void run(){
            while (count != 10){
                //Update Button Text
                Platform.runLater(()-> button.setText("Count:"+count));

                //Sleep for variation
                try {
                    Thread.sleep((long)((Math.random() * 3)+1)*1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                count++;
            }
            //Update Button Text
            Platform.runLater(()-> button.setText("DONE"));
        }
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM