2016-11-12 53 views
0

我的應用程序使用線程定期將字符串添加到列表。我想將這些字符串添加到列表後,立即將這些字符串添加到組合框。反正有沒有把組合框綁定到列表如何將ComboBox綁定到JavaFX中的列表?

我的代碼:

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

沒有就沒有辦法綁定一個簡單的列表,因爲它無法觀測。即使使用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; 
    } 
}; 
+0

我用Platform.runLater和它的作品。然而,我有一個奇怪的問題,如果我在填充它時打開了ComboBox,它一次只顯示一個可見項目,並將其他項目添加到scrolldown。但是,如果我在完成線程後打開組合框,它將顯示所有項目而沒有滾動顯示。 –

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()); 
相關問題