我正在尝试创建以下概念:每当启动特定屏幕时启动一个线程。该线程应该收到一条称为“标签”的消息,该消息尚未正常工作,因此我对其进行了硬编码。 然后根据标记的验证显示一个AnchorPane:showError或showValid函数。但是,应用程序首先运行该函数,然后显示AnchorPane和更新的ListView。
我想在特定屏幕启动时启动以下线程。
public class RFIDThread extends Thread{
private static final Logger logger = Logger.getLogger(RFIDApplication.class);
/**
* The incoming data stream from the LLRP reader connection
*/
private DataInputStream inStream = null;
/**
* The socket for the connection to the LLRP Reader
*/
private Socket socket = null;
/**
* A queue to store incoming LLRP Messages
*/
private LinkedBlockingQueue<LLRPMessage> queue = null;
private String[] found_tags = new String[5];
private JSONArray valid_tags;
private TagsListController controller;
/**
* Thread for constant reading of the stream
*
* @param socket
* @param controller
* @param tags
* @param orderNumber
* @throws java.io.IOException
*/
public RFIDThread(Socket socket, TagsListController controller, JSONArray tags, String orderNumber) throws IOException {
this.socket = socket;
this.controller = controller;
this.queue = new LinkedBlockingQueue<LLRPMessage>();
try {
this.inStream = new DataInputStream(socket.getInputStream());
} catch (IOException e) {
logger.error("Cannot get input stream", e);
}
valid_tags = tags;
found_tags[0] = "aga9jrjahr";
found_tags[1] = "agahs4suj";
found_tags[2] = "a79gtvaTGBQG";
found_tags[3] = "at3anit08av9agq4";
//found_tags[4] = "4a05355d0000000000017cc0";
//start();
}
@Override
public void run()
{
super.run();
if (socket.isConnected()) {
for (String found_tag : found_tags) {
Integer index = valid_tags.indexOf(found_tag);
if (index > 0) {
Platform.runLater(() -> {
controller.showValid(found_tag);
});
} else {
Platform.runLater(() -> {
controller.showError(found_tag);
});
}
}
}
}
}
线程应根据收到的标记运行函数:showError或showValid。目前我有一些硬编码标签设置都是无效的,所以它应该运行showError()函数。此函数:将标记添加到ListView,将标记设置为标签的文本,显示AnchorPane,休眠1秒,隐藏AnchorPane然后休眠1秒。在此之后,必须处理下一个标记。
/**
* Display red screen
* @param tag
*/
public void showError(String tag) {
this.found_tags_list.getItems().add(tag);
this.errorTag.setText(tag);
System.out.println(errorTag.getText());
this.errorPane.setVisible(true);
pause(1000);
this.validPane.setVisible(false);
pause(1000);
}
答案 0 :(得分:0)
您没有发布pause()
方法的代码,因此我假设它会执行类似Thread.sleep(...)
的操作并适当处理中断的异常。即我会假设你有类似的东西:
public void pause(int millis) {
try {
Thread.sleep(millis);
} catch (InterruptedException exc) {
Thread.currentThread().interrupt();
}
}
正在(明确)在FX应用程序线程上执行showError()
方法。该线程还负责呈现UI。因此,在执行showError()
方法时,不能重新绘制UI(因为单个线程不能同时执行两项操作:这基本上是&#34;的定义;&#34;螺纹&#34;。)
所以始终总是一个错误来阻止FX应用程序线程,因为它会使UI无响应并阻止它被绘制。
如果您已经在FX应用程序主题上,并希望将来安排某些代码执行,则可以使用PauseTransition
执行此操作。而不是
this.errorPane.setVisible(true);
pause(1000);
this.validPane.setVisible(false);
你可以做到
this.errorPane.setVisible(true);
PauseTransition pause = new PauseTransition(Duration.millis(1000));
pause.setOnFinished(e -> this.validPane.setVisible(false));
pause.play();
该方法中的第二个pause
不太合理。它只是暂停FX应用程序线程,然后该方法退出,所以它无论如何都没有等待。
如果想要让后台线程暂停,你应该在后台线程上调用pause()
。 (显然,在FX应用程序主题上调用它,不会让后台线程暂停。)
所以我认为你的代码应该是这样的:
public class RFIDThread extends Thread {
// ...
@Override
public void run() {
super.run();
if (socket.isConnected()) {
for (String found_tag : found_tags) {
Integer index = valid_tags.indexOf(found_tag);
if (index > 0) {
Platform.runLater(() -> controller.showValid(found_tag));
} else {
Platform.runLater(() -> controller.showError(found_tag));
}
pause(2000);
}
}
}
}
请注意,我猜这里的目的是让你的后台线程暂停(大约)一秒 你显示的窗格再次被隐藏,这意味着它需要暂停总共两秒钟。
在控制器中,你可以
public void showError(String tag) {
this.found_tags_list.getItems().add(tag);
this.errorTag.setText(tag);
System.out.println(errorTag.getText());
this.errorPane.setVisible(true);
PauseTransition pause = new PauseTransition(Duration.millis(1000));
pause.setOnFinished(e -> this.validPane.setVisible(false));
pause.play();
}