【问题标题】:Can I set the label text in JavaFX using threads?我可以使用线程在 JavaFX 中设置标签文本吗?
【发布时间】:2019-02-26 17:45:01
【问题描述】:

我想在不点击任何按钮等的情况下不断显示汽车的当前里程数。

线程类

package threads;

import javafx.fxml.FXML;
import javafx.scene.control.Label;

import static controller.GameWindowController.*;

public class MileageThread implements Runnable {


@FXML
Label mileageLabel;

@Override
public void run() {
    {
        double time = 1;
        while (true) {
            try {
                Thread.sleep(1000);
            } catch (NullPointerException | InterruptedException e) {
                e.printStackTrace();
            }
            getCar().setDistancePerSec((time * getCar().getCurrentCarSpeed()) / 3600);
            getCar().setCarMileage(getCar().getCarMileage() + getCar().getDistancePerSec());
            System.out.format("dziala %.3f km przebiegu %n", getCar().getCarMileage());
            mileageLabel.setText(String.valueOf(getCar().getCarMileage()));
        }
    }
}

}

我收到这条记录:

Exception in thread "Thread-5" java.lang.NullPointerException
at threads.MileageThread.run(MileageThread.java:27)

这是我创建线程的类:

package controller;

import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Label;
import javafx.scene.image.ImageView;
import model.VehicleStatus;
import threads.MileageThread;
import vehicles.Car;

import java.net.URL;
import java.util.ResourceBundle;

public class GameWindowController extends Thread implements Initializable, Runnable {

@FXML
ImageView smoke;

@FXML
private Label speedLabel, mileageLabel;

static Car car;

static {
    car = new Car() {
    };
}

public void accelerationButtonPushed(ActionEvent event) throws InterruptedException {
    car.accelerate();

    speedLabel.setText(String.valueOf(car.getCurrentCarSpeed()));

    smoke.setFitHeight(smoke.getX() + car.getCurrentCarSpeed());
    smoke.setFitWidth(smoke.getY() + car.getCurrentCarSpeed());

    System.out.println(car.getCurrentCarSpeed());
    System.out.println(car.getCarMileage());
    System.out.println(car.getFuel());
    System.out.println(car.getStatus());
}

public void stopCarButtonPushed(ActionEvent event) throws InterruptedException {

    if (car.getCurrentCarSpeed() == 0) {
        System.out.println("Silnik zgasl!");
    }
    car.stop();

    speedLabel.setText(String.valueOf(car.getCurrentCarSpeed()));
    smoke.setFitHeight(smoke.getX() + car.getCurrentCarSpeed());
    smoke.setFitWidth(smoke.getY() + car.getCurrentCarSpeed());

    System.out.println(car.getCurrentCarSpeed());
    System.out.println(car.getCarMileage());
    System.out.println(car.getFuel());
    System.out.println(car.getStatus());
}

public void startButtonPushed(ActionEvent event) throws InterruptedException {
    if (car.getStatus() != VehicleStatus.MOVING) {
        car.start();
    } else System.out.println("Samochod juz jest na chodzie!");

    System.out.println("Status pojazdu: " + car.getStatus());
}

@FXML
public void initialize(URL location, ResourceBundle resources) {
    smoke.setFitHeight(1);
    smoke.setFitWidth(1);

    MileageThread mileageThread = new MileageThread();
    Thread mt = new Thread(mileageThread);
    mt.start();

}

public static Car getCar() {
    return car;
}

}

如果您在这里发现一些基本错误或我误解了您,我深表歉意。

我正在使用场景构建器,我只想使用 MileageThread 将文本放在其中一个标签中。

【问题讨论】:

  • A minimal reproducible example 证明问题也会有所帮助。
  • 如 stopCarButtonPushed() 或AccelerationCarButtonPushed()。我在那里设置了 speedLabel,这是我的车速表,但它仅在按下按钮时更新。而且我想显示波形而不需要按按钮,例如上面的线程但是我编写它的方式不起作用。
  • 假设更新了Car 的适当线程安全,您可以使用定期更新LabelTimeline。见JavaFX periodic background task
  • 非常感谢。这篇文章帮助了我。我用过:PauseTransition
  • 不相关:摆脱所有这些静态...

标签: java multithreading javafx nullpointerexception


【解决方案1】:

如果您想从 JavaFX 应用程序线程以外的线程修改用户界面,您必须将其包装在对 Platform.runLater() 的调用中

Platform.runLater(() -> {
    userInterfaceControl.setText("New Text");
});

JavaFX 节点/控件/等。只能从 JavaFX 应用程序线程修改。

【讨论】:

  • Platform.runLater 对我不起作用。我使用 PauseTransition。无论如何谢谢你的帮助:)
【解决方案2】:

对我有用的解决方案:

@FXML
    public void initialize(URL location, ResourceBundle resources) {
        PauseTransition wait = new PauseTransition(Duration.seconds(1));
    wait.setOnFinished((e) -> {
        mileageLabel.setText(String.valueOf(getCar().getCarMileage()));
        wait.playFromStart();
    });
    wait.play();
}

希望有人能帮忙:)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多