我的应用程序会定期使用线程将字符串添加到列表。我想将这些字符串添加到列表后立即添加到 ComboBox 。无论如何将 ComboBox 绑定到列表?
我的代码:
static final int max = 20;
List<String> ips = new ArrayList<String>();
public void getIP() throws UnknownHostException {
Task task = new Task<Void>() {
@Override
public Void call() throws UnknownHostException {
InetAddress localhost = InetAddress.getLocalHost();
byte[] ip = localhost.getAddress();
for (int i = 10; i <= max; i++) {
if (isCancelled()) {
break;
}
try {
ip[3] = (byte) i;
InetAddress address = InetAddress.getByAddress(ip);
if (address.isReachable(100)) {
//============================== Populating List ===============//
ips.add(address.getHostName());
}
} catch (Exception e) {
System.err.println(e);
}
updateProgress(i, max);
}
return null;
}
};
//============================== Bind ComboBox to List Code here ===============//
indicator.progressProperty().bind(task.progressProperty());
new Thread(task).start();
}
答案 0 :(得分:0)
没有办法绑定一个简单的列表,因为它不可观察。即使使用ObservableList
,也会出现来自不同线程的更新问题。
但是,您可以使用同步列表并使用value属性传递当前大小,这样您就可以通过侦听器添加项目。
示例强>
这使用ListView
代替ComboBox
,因为结果在没有用户互动的情况下可见,但您也可以使用targetList = comboBox.getItems()
。
@Override
public void start(Stage primaryStage) {
ListView<String> listView = new ListView<>();
List<String> targetList = listView.getItems();
final List<String> ips = Collections.synchronizedList(new ArrayList<>());
Task<Integer> task = new Task<Integer>() {
@Override
protected Integer call() throws Exception {
Random random = new Random();
int size;
for (size = 0; size < 100; size++) {
ips.add(Integer.toString(size));
updateValue(size);
Thread.sleep(random.nextInt(500));
}
return size;
}
};
task.valueProperty().addListener((observable, oldValue, newValue) -> {
// add values not yet in the target list.
for (int i = targetList.size(), newSize = newValue; i < newSize; i++) {
targetList.add(ips.get(i));
}
});
new Thread(task).start();
Scene scene = new Scene(listView);
primaryStage.setScene(scene);
primaryStage.show();
}
虽然简单地使用Platform.runLater
在ui线程上发布更新会更简单:
ips = comboBox.getItems();
Task task = new Task<Void>() {
@Override
public Void call() throws UnknownHostException {
InetAddress localhost = InetAddress.getLocalHost();
byte[] ip = localhost.getAddress();
for (int i = 10; i <= max; i++) {
if (isCancelled()) {
break;
}
try {
ip[3] = (byte) i;
InetAddress address = InetAddress.getByAddress(ip);
if (address.isReachable(100)) {
//============================== Populating List ===============//
final String hostName = address.getHostName();
// do update on application thread
Platform.runLater(() -> ips.add(hostName));
}
} catch (Exception e) {
System.err.println(e);
}
updateProgress(i, max);
}
return null;
}
};
答案 1 :(得分:0)
我建议你做以下事情:
变化
List<String> ips = new ArrayList<String>();
到
final ObservableList<String> ips = FXCollections.observableArrayList();
变化:
Task task = new Task<Void>()
到
Task<ObservableList<String> task = new Task<>(){
@Override
public ObservableList<String> call() throws UnknownHostException {
...
return ips;
}
};
comboBox.itemsProperty().bind(task.valueProperty());