2017-03-07 39 views
2

在回答關於ChoiceBox的問題時,我發現了一個有趣的問題(錯誤,可能是?)。在Java 1.8u60中,爲ChoiceBox添加了以下四種方法:setOnShown,setOnShowing,setOnHidden,setOnHiding。但我無法讓他們工作!ChoiceBox onShown onHidden方法不起作用JavaFX

public class ComboBoxSample extends Application { 

    public static void main(String[] args) { 
     launch(args); 
    } 

    @Override public void start(Stage stage) { 
     stage.setTitle("ComboBoxSample"); 
     Scene scene = new Scene(new Group(), 450, 250); 

     final ComboBox<String> comboBox = new ComboBox<>(); 
     comboBox.getItems().addAll(
       "[email protected]", 
       "[email protected]" 
     ); 

     comboBox.setOnShown(event -> { 
      System.out.println("ComboBox onShown"); 
      System.out.println(comboBox.getSelectionModel().getSelectedIndex()); 
     }); 
     comboBox.setOnShowing(event -> { 
      System.out.println("ComboBox setOnShowing"); 
      System.out.println(comboBox.getSelectionModel().getSelectedIndex()); 
     }); 

     ChoiceBox<String> choiceBox = new ChoiceBox<>(); 
     choiceBox.setItems(FXCollections.observableArrayList(
       "New Document", "Open ") 
     ); 

     choiceBox.setOnShown(event -> { 
      System.out.println("ChoiceBox onShown"); 
      System.out.println(choiceBox.getSelectionModel().getSelectedIndex()); 
     }); 

     choiceBox.setOnShowing(event -> { 
      System.out.println("ChoiceBox onShowing"); 
      System.out.println(choiceBox.getSelectionModel().getSelectedIndex()); 
     }); 

     choiceBox.setOnHidden(event -> { 
      System.out.println("ChoiceBox setOnHidden"); 
      System.out.println(choiceBox.getSelectionModel().getSelectedIndex()); 
     }); 

     choiceBox.getSelectionModel().selectedIndexProperty().addListener(e -> { 
      System.out.println("ChoiceBox selectedIndexProperty"); 
     }); 

     GridPane grid = new GridPane(); 
     grid.setVgap(4); 
     grid.setHgap(10); 
     grid.setPadding(new Insets(5, 5, 5, 5)); 
     grid.add(new Label("ComboBox: "), 0, 0); 
     grid.add(comboBox, 1, 0); 
     grid.add(new Label("ChoiceBox: "), 0, 1); 
     grid.add(choiceBox, 1, 1); 

     Group root = (Group)scene.getRoot(); 
     root.getChildren().add(grid); 
     stage.setScene(scene); 
     stage.show(); 
    } 
} 

對於ComboBoxsetOnShownsetOnShowing方法工作得很好,但對於ChoiceBox控制檯輸出是除了selectedIndexProperty聽衆空。 這是一個已知的bug嗎?'因爲我找不到任何相關的東西。或者代碼有問題?

我使用最新的JDK v1.8.0_121。

+0

[文檔](https://docs.oracle .com/javase/8/javafx/api/javafx/scene/control/ChoiceBox.html)甚至沒有列出這些方法r'ChoiceBox',所以我很驚訝它編譯... – Itai

+0

@sillyfly是的,我已經向Oracle團隊提交了一個錯誤。 – Enigo

回答

1

是的,它確實似乎是一個錯誤。

檢查ChoiceBox的代碼得出以下結果:ChoiceBox以錯誤的事件類型觸發這些事件。

當您設置執行以下代碼處理:

private ObjectProperty<EventHandler<Event>> onShown = new ObjectPropertyBase<EventHandler<Event>>() { 
    @Override protected void invalidated() { 
     setEventHandler(ON_SHOWN, get()); 
    } 

    .... 
}; 

其中ON_SHOWN被定義爲ChoiceBox的靜態字段:

public static final EventType<Event> ON_SHOWN = 
     new EventType<Event>(Event.ANY, "CHOICE_BOX_ON_SHOWN"); 

然而,當事件被觸發.. 。

Event.fireEvent(this, value ? new Event(ComboBoxBase.ON_SHOWN) : 
      new Event(ComboBoxBase.ON_HIDDEN)); 

...它使用ComboBoxBase.ON_SHOWN ev ent類型。

它似乎是一個複製粘貼忘記更新問題。

總之:他們不工作,因爲當你設置處理程序時,他們期待錯誤的事件類型。


作爲一種變通方法,直到它被固定,你可以聽在ComboBoxBase定義的解僱事件類型。

隨着EventFilter

choiceBox.addEventFilter(ComboBoxBase.ON_SHOWN, e -> 
    System.out.println("ComboBoxBase.ON_SHOWN was fired")); 

或與EventHandler

choiceBox.addEventHandler(ComboBoxBase.ON_SHOWN, e-> 
    System.out.println("ComboBoxBase.ON_SHOWN was fired")); 

JDK錯誤票:JDK-8175963 : ChoiceBox using events from ComboBox

+0

偉大的解決方案!當然,使用'ChoiceBox'的ComboBoxBase'事件類型看起來有點奇怪)無論如何,我已經向Oracle團隊提交了一個bug。 – Enigo

+0

通過指向JDK票證的鏈接更新了答案。 – DVarga