刷新线程中的Java FX窗口

时间:2019-01-22 02:22:33

标签: java javafx client-server java-threads

我有客户端-服务器应用程序,客户端有两个线程,一个线程用于向服务器发送信息,另一个线程应显示变化的窗口,但出现错误。我已经阅读了有关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();
}
}

请帮助:<< / p>

3 个答案:

答案 0 :(得分:0)

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

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

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

答案 1 :(得分:0)

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

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) );
    }
}

答案 2 :(得分:0)

这是一个简单的示例,向您展示如何使用B,我尝试使其与您的应用程序相似,但我的方法被愚蠢了,我也在其中添加了一些评论

Platform.runLater(()-> ...);