我有一个JavaFX应用程序,它读取标签,然后将它们放入带有HBox(标签和按钮)的VBox列表中。但是,当需要处理大量标签时,应用程序非常慢。我该如何优化此流程?我遇到的另一个问题是光标和应用程序在加载/处理新标签时卡住/休眠,我能以某种方式修复此问题,以便线程在后台运行,我仍然可以使用我的应用程序吗?
我自己的主题:
package nl.fermrfid.application.rfidreader;
import javafx.application.Platform;
import javafx.collections.FXCollections;
import javafx.scene.Node;
import org.json.simple.JSONArray;
import java.io.IOException;
import java.net.Socket;
import java.util.Collection;
import java.util.concurrent.CopyOnWriteArrayList;
public class RFIDThread implements Runnable
{
/**
* The socket for the connection to the LLRP Reader
*/
private Socket socket;
private JSONArray valid_tags;
private JSONArray found_tags;
private TagsListController controller;
private RFIDSet rfidset;
/**
* Thread for constant reading of the stream
*
* @param socket
* @param controller
* @param tags
*/
public RFIDThread(Socket socket, TagsListController controller, JSONArray tags, RFIDSet rfidset) {
this.socket = socket;
this.controller = controller;
this.rfidset = rfidset;
this.found_tags = new JSONArray();
this.valid_tags = tags;
}
/**
* Runnable for this thread.
* First get all the found tags from the xml controller
* Then loop over the rfid set to find any new tags.
* If there are any, display them.
*/
@Override
public void run()
{
if (socket.isConnected()) {
while (!socket.isClosed()) {
CopyOnWriteArrayList<Tag> set = new CopyOnWriteArrayList<>();
set.addAll(this.rfidset.getSet());
Collection<String> found_set = FXCollections.observableSet();
this.found_tags.clear();
for(Node n : this.controller.found_tags_box.getChildren()) {
this.found_tags.add(n.getId());
}
for (Tag found_tag : set) {
String tag_id = found_tag.getId();
if (found_tags.indexOf(tag_id) < 0) {
found_tags.add(tag_id);
found_set.add(tag_id);
}
}
Platform.runLater(() -> controller.addAllFoundTags(found_set));
pause(2000);
}
}
}
/**
* Close the socket
*/
public void shutdown()
{
try {
this.socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
private void pause(long ms)
{
try {
Thread.sleep(ms);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
启动我自己的线程的启动线程方法:
/**
* Start the rfid thread
* @param rfidset
* @param action
* @param textOrder
*/
public void startThread(RFIDSet rfidset, Action action, String textOrder)
{
String readerId = RFIDApplication.getContext().getProperties().getProperty(SETTINGS_READERS);
String host = RFIDApplication.getContext().getProperties().getProperty(String.format(SETTINGS_READER_HOST, readerId));
String port = RFIDApplication.getContext().getProperties().getProperty(String.format(SETTINGS_READER_PORT, readerId));
this.rfidset = rfidset;
this.action = action;
this.textOrder = textOrder;
// Preparing management server instance ...
this.server = RFIDApplication.server;
// Preparing RFID reader instance ...
this.reader = RFIDApplication.reader;
try {
thread = new RFIDThread(new Socket(host, Integer.parseInt(port)), this, valid_tags, rfidset);
new Thread(thread).start();
} catch (IOException e) {
e.printStackTrace();
}
}
找到新标记时需要将其放入列表中的方法。这是一种非常难看的方法。
public void addAllFoundTags(Collection<String> tags)
{
for(String tag_id : tags) {
Integer index = valid_tags.indexOf(tag_id);
Label label = new Label(tag_id);
label.setTextFill(index >= 0 ? Color.GREEN : Color.RED);
Image cancel = new Image("/cancel.png", 14, 14, false, false);
Button butt = new Button();
butt.setGraphic(new ImageView(cancel));
butt.setStyle("-fx-background-color: transparent;");
butt.setOnAction(event -> {
for (Tag tag : rfidset.getSet()) {
if (tag.getId().equals(tag_id)) {
rfidset.remove(tag);
for(Node n : found_tags_box.getChildren()) {
if(n.getId().equals(tag_id)) {
found_tags_box.getChildren().remove(n);
break;
}
}
tags_amount.setText(Integer.toString(Integer.parseInt(tags_amount.getText()) - 1));
return;
}
}
});
HBox hBox = index >= 0 ? new HBox(label) : new HBox(label, butt);
if (even) hBox.setStyle("-fx-background-color: #F9F9F9");
hBox.setId(tag_id);
hBox.setPrefHeight(25.0);
hBox.setMinHeight(25.0);
hBox.setMaxHeight(25.0);
hBox.setAlignment(Pos.CENTER_LEFT);
hBox.setPadding(new Insets(0, 0, 0, 10));
even = !even;
this.found_tags_box.getChildren().add(hBox);
}
tags_amount.setText(Integer.toString(this.found_tags_box.getChildren().size()));
this.scroll_pane.setVvalue(1.0);
}