2016-11-12 4 views
0

Мое приложение периодически добавляет строки в список с использованием Thread. Я хочу добавить эти строки в ComboBox, как только они будут добавлены в список . Есть ли все равно, чтобы связать ComboBox с Список? НеКак связать 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 хотя:

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, когда я заполняю ее, она отображает только один видимый элемент за раз и добавляет остальных в прокрутку. Однако, если я открою ComboBox после завершения моего потока, он отобразит все элементы просто отлично без прокрутки. –

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());