【问题标题】:Combobox clearing value issue组合框清除值问题
【发布时间】:2012-08-21 23:20:50
【问题描述】:

我偶然发现了 javafx2.2 中组合框的问题。这是场景:

  • 用户点击“editFile”按钮。
  • 另一个窗格变得可见(使用 setVisible 方法)。

此窗格包含 6 个组合框。 其中三个有固定项目:cboReport、cboSales、cboSend。其中三个从 db (ObservableList) 获取数据并在窗格可见时填充:cboFile、cboCustomer、cboVet

  • 用户从 cboFile 中选择一个文件编号。其余的组合框都设置了正确的值。
  • 用户按下保存按钮,文件按预期保存。
  • 接下来用户按下关闭按钮。

当窗口关闭时,窗格上的数据通过 resetGUI_editFilePane() 方法重置。有这样的行:

...
cboReport.getSelectionModel().clearSelection();
cboSales.getSelectionModel().clearSelection();
cboSend.getSelectionModel().clearSelection();
cboFile.getSelectionModel().clearSelection();
cboCustomer.getSelectionModel().clearSelection();
cboVet.getSelectionModel().clearSelection();

cboFile.getItems().clear();
cboCustomer.getItems().clear();
cboVet.getItems.clear();
...

当用户通过按下“editFile”按钮再次打开窗格时,我注意到只有“固定项目”组合框已清除他们的选择,动态填充的组合框显示最后选择的项目,尽管选择本身的值是 @ 987654323@。这对我来说像是一个图形错误,还是我做错了什么?

有没有办法解决这个问题或者重置组合框的最佳方法是什么?

编辑 2014/08/27:
这正式不是bug(clearSelection() 不清除值):
https://bugs.openjdk.java.net/browse/JDK-8097244

官方的“解决方法”是清除选择后清除ComboBox的值。

cb.getSelectionModel().clearSelection();
// Clear value of ComboBox because clearSelection() does not do it
cb.setValue(null);

【问题讨论】:

    标签: combobox javafx-2 javafx-8 selectionmodel


    【解决方案1】:

    我遇到了几乎完全相同的情况,并在寻找解决方案时遇到了您的问题。幸运的是,我想出了一个强制组合框重置的解决方法。当您重置窗格上的数据时,而不是执行以下操作:

    cboVet.getSelectionModel().clearSelection();
    cboVet.getItems.clear();
    

    做这样的事情......

    parentNode.getChildren().remove(cboVet);
    cboVet = new ComboBox();  // do whatever else you need to format your ComboBox
    parentNode.add(cboVet);
    

    您还需要在您的 ComboBox 上再次执行 setItems(),以便填充新的 ComboBox。这不是一个理想的解决方案,但它似乎可以正常工作,正如我所期望的那样提供 clearSelection() 方法。

    【讨论】:

    • 对于 1.7.25+ 的用户,执行 myCombobox.getSelectionModel().clearSelection(); 对我来说效果很好。无需删除整个组合框或任何东西
    【解决方案2】:

    我使用反射直接操作 ComboBox 皮肤中的 buttonCell 字段:

    @SuppressWarnings({ "rawtypes", "unchecked" })
    public static <T> void resetComboBox(ComboBox<T> combo) {
        Skin<?> skin = combo.getSkin();
        if(skin==null){
            return;
        }
        combo.setValue(null);
        Field buttonCellField;
        try {
            buttonCellField = skin.getClass().getDeclaredField("buttonCell");
            buttonCellField.setAccessible(true);
            ListCell buttonCell = (ListCell) buttonCellField.get(skin);
            if(buttonCell!=null){
                StringProperty text = buttonCell.textProperty();
                text.set("");
                buttonCell.setItem(null);
            }
        } catch (NoSuchFieldException 
                | SecurityException 
                | IllegalArgumentException 
                | IllegalAccessException e) {
            e.printStackTrace();
        }
    
    }
    

    我认为也可以通过 buttonCellFactory 属性提供自己的 buttonCell 实现

    【讨论】:

      【解决方案3】:

      您可以检索项目并将它们全部删除:

      cboVet.getItems().removeAll(cboVet.getItems());
      

      【讨论】:

        【解决方案4】:

        我在使用 ComboBox 时遇到了同样的问题。当我更改 ComboBox 的项目时,ComboBox 的 buttonCell 未正确更新。这看起来像一个图形错误。

        我使用直接操作 ComboBox 中的 buttonCell 字段。

        combo.getButtonCell().setText("");
        combo.getButtonCell().setItem(null);
        

        这是我找到的最好的解决方案,无需重新创建 ComboBox。

        【讨论】:

          【解决方案5】:

          我刚刚使用 Java JDK 1.7.11 测试了一个可行的解决方案:

          combobox.setSelectedItem(null);
          combobox.setValue(null);
          

          希望对你有帮助:)

          【讨论】:

          • 是的,ComboBox.setValue(null);或者在我的例子中 ChoiceBox.setValue(null) 似乎是完成所要求的最简单的方法。接受的答案似乎有点矫枉过正,这要简单得多
          【解决方案6】:

          要清除 SelectionModel,我发现没有比创建 Combobox 的新实例更好的了(之前的答案更新):

          myParentNode.getChildren().remove(myCombobox);
          myCombobox = new ComboBox();
          myParentNode.add(myCombobox);
          

          但是这个解决方案会带来其他问题:如果你使用 fxml,这个组合框将被放置在错误的位置和错误的参数。一些 fxml 参数很难直接从控制器类代码中复制出来,每次需要清除组合框时都这样做很糟糕。

          解决方案是使用自定义组件,而不是直接在主控制器类代码中创建实例,即使这些组件是标准的。这也有助于释放主控制器类中的一些行,方法是将组件相关的事件方法和其他方法移动到单独的类文件中,在其中使用对主控制器类的引用。

          如何在 JavaFX FXML 应用程序中创建自定义组件可以在 http://docs.oracle.com/javafx/2/fxml_get_started/custom_control.htm 中找到,但请注意,如果应用程序中的每个自定义组件已经有一个带有 start(Satge 阶段)的入口点类,则不需要 CustomControlExample 类方法。

          如何解决从自定义组件控制器类到主控制器类的引用可能出现的错误可以在JavaFx: how to reference main Controller class instance from CustomComponentController class?中找到

          【讨论】:

            【解决方案7】:

            这很简单。您只需要使用 ComboBox 的 value 属性。给你....

            ComboBox c;
            c.valueProperty().set(null);
            

            我希望这对你有用:-D

            【讨论】:

            • 非常感谢!!拯救了我的一天。这是这个问题的实际答案。
            • 很高兴帮助卡拉施尼。我很高兴这个解决方案对你有用。
            • 这也是官方的“解决”方式。请参阅上面的编辑 2014/08/27。
            • 谢谢。一直在找这个。
            【解决方案8】:

            我需要清除组合框的选择。这段代码对我有用:

             List<Object> list = new ArrayList<>(comboBox.getItems());
             comboBox.getItems().removeAll(list);
             comboBox.getItems().addAll(list);
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2014-02-06
              • 2011-12-29
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2012-03-08
              相关资源
              最近更新 更多