javafx - 如何在循环中更新 javafx 中的文本字段?
问题描述
我有一个使用场景构建器的小型 javafx 应用程序,单击按钮时应定期从 COM 端口读取字符串并在文本字段中更新。
但是现在如果我使用 for 循环,它只显示最后一个字符串,如果我将代码放入无限循环中则什么都不会显示(这是我的临时要求)。
任何人都可以帮助我,以便在每次从 COM 端口读取时,新字符串都会在文本字段中更新。
这是我用于这两种情况的代码:
注意:在控制器类的这两种情况下,我都在控制台上获得了完美的输出。
public class Main extends Application
{
@Override
public void start(Stage primaryStage)
{
try
{
Parent root = FXMLLoader.load(getClass().getResource("test.fxml"));
Scene scene = new Scene(root);
//scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
primaryStage.setTitle("test");
primaryStage.setScene(scene);
primaryStage.show();
}
catch(Exception e)
{
e.printStackTrace();
}
}
public static void main(String[] args)
{
launch(args);
}
}
这是控制器类:
// In this case it shows only the last string in the text field.
public class Controller implements Initializable
{
@FXML
private Button sayHelloButton;
@FXML
private TextField helloField;
@Override
public void initialize(URL arg0, ResourceBundle arg1)
{
}
@FXML
public void printHello(ActionEvent event)
{
if(event.getSource() == sayHelloButton)
{
SerialPort serialPort = new SerialPort("COM22");
for(int i=0;i<5;i++)
{
try
{
if(!serialPort.isOpened())
{
serialPort.openPort();
serialPort.setParams(9600, 8, 1, 0);
}
String str = serialPort.readString(10,3000);
System.out.println(str);
helloField.clear();
helloField.setText(str);
}
catch(Exception e)
{
helloField.setText(e.toString());
}
}
}
}
}
这是无限循环的方法:
//this shows nothing in the text field
@FXML
public void printHello(ActionEvent event)
{
if(event.getSource() == sayHelloButton)
{
SerialPort serialPort = new SerialPort("COM22");
while(true)
{
try
{
if(!serialPort.isOpened())
{
serialPort.openPort();
serialPort.setParams(9600, 8, 1, 0);
}
String str = serialPort.readString(10,3000);
System.out.println(str);
helloField.clear();
helloField.setText(str);
}
catch(Exception e)
{
helloField.setText(e.toString());
}
}
}
}
解决方案
这里发生了几件事。在您的第一个示例中,您声明控制台输出是正确的,但TextField
仅显示最后一个结果。
如果循环快速执行,这是预期的。TextField
正在更新,但它发生得如此之快,以至于在循环结束并且仍在显示最后一个结果之前您看不到它。即使您在循环中内置了延迟,这仍然会阻止 UI 更新,直到循环完成。
对于您的无限循环,问题在于循环正在JavaFX 应用程序线程(JFXAT) 上运行。这会阻止对 GUI 的任何更新,直到循环完成,这永远不会。
您需要将无限循环移动到新的后台线程。Platform.runLater()
从那里,您可以使用该方法更新 GUI 。
SerialPort serialPort = new SerialPort("COM22");
new Thread(() -> {
while(true)
{
try
{
if(!serialPort.isOpened())
{
serialPort.openPort();
serialPort.setParams(9600, 8, 1, 0);
}
String str = serialPort.readString(10,3000);
System.out.println(str);
// Update the UI on the JavaFX Application Thread
Platform.runLater(() -> {
helloField.clear();
helloField.setText(str);
});
}
catch(Exception e)
{
Platform.runLater(() -> helloField.setText(e.toString()));
}
}
}).start();
这允许您的 UI 在后台线程向其发送新信息时不断更新。
推荐阅读
- azure - Azure 权限:无权执行此操作
- python - numpy 遗传算法选择:轮盘赌 vs. 随机通用采样
- javascript - 属性在对象中,但显示为未定义
- postgresql - 如何在聚合中包含下一组的第一行?
- phpstorm - 如何阻止 PhpStorm 从变量名中去除单引号
- c - 由于“没有这样的文件或目录”,无法创建共享库
- powershell - Powershell import-csv $variable 正确为空
- encryption - 如何构建高度安全的端到端加密 React Native 消息传递应用程序
- django - 从 UserCreationForm 中删除用户名并根据电子邮件、名字和姓氏为用户自动生成用户名
- sql-server - DATEADD 仅限工作日