2014-08-30 63 views
1

我想使用兩個ChoiceBoxes提供相同的選擇項目,但另一個選擇項目除外。但是,在幾次選擇選項之後,整個java進程變得沒有響應。ChoiceBox:從另一個選擇框中刪除選定項目時凍結

更新:如果我使用ComboBox而不是ChoiceBox,則不會發生該問題。然而,爲什麼會發生這樣的解釋會很有趣。

我有兩個ChoiceBoxes

@FXML private ChoiceBox<String> firstCB; 
@FXML private ChoiceBox<String> secondCB; 

最初具有相同的選擇選項

firstCB.getItems().addAll(Charset.availableCharsets().keySet()); 
secondCB.getItems().addAll(Charset.availableCharsets().keySet()); 

和事件監聽器再次刪除從其他ChoiceBox的選擇新的選擇並提供舊選項

firstCB.getSelectionModel().selectedItemProperty() 
.addListener((observable, oldVal, newVal) -> { 
    secondCB.getItems().remove(newVal); 
    secondCB.getItems().add(oldVal); 
}); 

與JComboBoxe等效的Swing代碼S和下面的事件處理工作

firstCB.addItemListener(itemEvent -> { 
    if (itemEvent.getStateChange() == ItemEvent.DESELECTED) { 
    secondCB.addItem((String) itemEvent.getItem()); 
    } else if (itemEvent.getStateChange() == ItemEvent.SELECTED) { 
    secondCB.removeItem(itemEvent.getItem()); 
    } 
}); 

全碼:

類test.Main

public class Main extends Application { 
    private Parent rootPane; 
    @Override 
    public void start(Stage arg0) throws Exception { 
    Scene scene = new Scene(rootPane); 
    arg0.setScene(scene); 
    arg0.show(); 
    } 
    @Override 
    public void init() throws Exception { 
    FXMLLoader loader = new FXMLLoader(getClass().getResource("/main.fxml")); 
    rootPane = loader.load(); 
    loader.<View>getController().init(); 
    } 
    public static void main(String[] args) { 
    launch(args); 
    } 
} 

類test.View

public class View { 
    @FXML 
    private ChoiceBox<String> firstCB; 
    @FXML 
    private ChoiceBox<String> secondCB; 
    public void init() { 
    firstCB.getItems().addAll(Charset.availableCharsets().keySet()); 
    secondCB.getItems().addAll(Charset.availableCharsets().keySet()); 
    firstCB.getSelectionModel().selectedItemProperty() 
     .addListener((observable, oldVal, newVal) -> { 
      System.out.printf("[%s]firstCB selection changed%n", Thread.currentThread().getName()); 
      secondCB.getItems().remove(newVal); 
      secondCB.getItems().add(oldVal); 
     }); 
    // removing one of the event listeners doesn't help 
    secondCB.getSelectionModel().selectedItemProperty() 
     .addListener((observable, oldVal, newVal) -> { 
      System.out.printf("[%s]secondCB selection changed%n", Thread.currentThread().getName()); 
      firstCB.getItems().remove(newVal); 
      firstCB.getItems().add(oldVal); 
     }); 
    } 
} 

main.fxml

<?xml version="1.0" encoding="UTF-8"?> 
<?import javafx.scene.control.*?> 
<?import java.lang.*?> 
<?import javafx.scene.layout.*?> 
<Pane fx:id="rootPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="90.0" prefWidth="180.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="test.View"> 
    <children> 
     <ChoiceBox fx:id="firstCB" layoutX="14.0" layoutY="14.0" prefWidth="150.0" /> 
     <ChoiceBox fx:id="secondCB" layoutX="14.0" layoutY="52.0" prefWidth="150.0" /> 
    </children> 
</Pane> 
+0

看起來像一個用法錯誤,給我等不是最好的解決辦法:從choicebox API文檔「ChoiceBox使用用於向用戶呈現**相對較小的一組 預定義的選項「 - 它不針對處理較大的項目計數而優化(如同ComboBox,fi通過虛擬化節點) – kleopatra 2014-08-31 09:06:56

回答

1

試試這個,它工作正常,我

firstComboBox.valueProperty().addListener((obs, oldV, newV) -> { 
     secondComboBox.getItems().remove(newV); 
     if(oldV!= null) secondComboBox.getItems().add(oldV); 
    }); 

secondComboBox.valueProperty().addListener((obs, oldV, newV) -> { 
     firstComboBox.getItems().remove(newV); 
     if(oldV!= null) firstComboBox.getItems().add(oldV); 
    }); 

或可觀察和篩選列表

public class Controller implements Initializable{ 
public ComboBox<String> firstComboBox; 
public ComboBox<String> secondComboBox; 

@Override 
public void initialize(URL location, ResourceBundle resources) { 
    ObservableList<String> list = FXCollections.observableArrayList(); 
    list.addAll("one", "two", "three", "four", "five"); 
    firstComboBox.getItems().addAll(list); 
    secondComboBox.getItems().addAll(list); 

    firstComboBox.valueProperty().addListener(c -> refreshList(list, secondComboBox, firstComboBox)); 
    secondComboBox.valueProperty().addListener(c -> refreshList(list, firstComboBox, secondComboBox)); 
} 

private void refreshList(ObservableList<String> list, ComboBox<String> choiceBox, ComboBox<String> choiceBox2) { 
    String tmp = choiceBox.getValue(); 
    FilteredList<String> filteredList = new FilteredList<>(list, string -> !string.equals(choiceBox2.getValue())); 
    choiceBox.setItems(filteredList); 
    choiceBox.setValue(tmp); 
} 
+0

您的代碼確實有效,但這似乎是由於您使用** Combo ** Boxes而不是** Choice ** Boxes。更改我的原始代碼以使用Combo-而不是ChoiceBoxes修復了問題;反過來改變你的代碼使用ChoiceBoxes會導致同樣的問題。 – 2014-08-31 07:49:50

相關問題