【问题标题】:Javafx combobox not updating dropdown size upon change on realtime?Javafx组合框在实时更改时不更新下拉大小?
【发布时间】:2015-11-18 20:38:03
【问题描述】:

我正在使用 Javafx v8.0.25-b18。

我遇到的问题是动态组合框的下拉列表的大小没有改变,所以如果我最初在下拉列表中有两个项目,那么下拉列表的大小将适合两个项目,但是如果我现在填充包含三个项目的动态组合框然后我在里面得到一个小滚动条!?,如果我删除一个项目 - 我将在组合框中有一个空白空间!?

每次我将值放入其中时,我都想“重置”下拉列表的大小,因此每次在运行时填充它时它都会是正确的大小。

为了更清楚,我添加了三张图片:
1. 第一张截图显示初始下拉大小为 2

  1. 第二个屏幕截图显示了相同的组合框,现在在运行时我添加了 2 个值,我希望它现在有一个大小为 4 的下拉列表,但下拉列表大小保持为 2 并且只添加了一个不需要的滚动条李>

  1. 最后一个屏幕截图是当我删除项目并且只有一个项目保留在组合框中时,我希望看到一个下拉菜单,但不幸的是我看到一个大小为 2 的下拉菜单,因此是一个空白空间而不是第二个项目

我正在添加简单的代码来创建这个场景,我要感谢@Gikkman 帮助我们走到了这一步,代码实际上是他的!

public class Test extends Application {

private int index = 0;

@Override
public void start(Stage primaryStage) throws IOException {

VBox vbox =  new VBox();
vbox.setSpacing(10);
vbox.setAlignment(Pos.CENTER);

final ComboBox<String> box = new ComboBox<>();
box.setPrefWidth(200);
box.setVisibleRowCount(10);

Button add = new Button("Add");
Button remove = new Button("Remove");

add.setOnAction(    new EventHandler<ActionEvent>() {
  @Override
  public void handle(ActionEvent event) {
    box.getItems().add("Item " + index++);
    box.getItems().add("Item " + index++);
  }
});


remove.setOnAction( new EventHandler<ActionEvent>() {
  @Override
  public void handle(ActionEvent event) {
    if( index > 0 )
      box.getItems().remove(--index);
  }
});


vbox.getChildren().addAll(add, remove, box);


Scene scene = new Scene(vbox);

primaryStage.setScene(scene);
primaryStage.show();
}

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

【问题讨论】:

  • 请提供MVCE。
  • 用谷歌搜索但不明白 MVCE 代表什么。你能详细说明一下吗?
  • 好的,现在我有一个很好的 MVCE
  • 我无法观察您描述的场景。添加和删​​除项目会按预期显示下拉列表。如果项目大小超过 10,则会出现滚动条,这是因为 VisibleRowCount 的默认值为 10。即使您说您正在重用 JavaFX 2,您附加的屏幕截图来自 JavaFX 8 引入的 modena 样式。检查System.out.println( com.sun.javafx.runtime.VersionInfo.getRuntimeVersion() ) 的确切版本。
  • 对不起,你是对的,版本是:8.0.25-b18,我现在去把原帖里的版本改一下。您描述的行为是我想要的,但是使用我在帖子中输入的确切代码,我得到了我描述的行为,如果是版本问题,我不介意升级,谢谢 Uluk

标签: javafx combobox javafx-8


【解决方案1】:

就像在这里提供我的两分钱。您可以将以下代码添加到您的组合框中,该组合框定义了一个自定义列表视图弹出窗口,该弹出窗口根据当前项目数具有可变高度。您可以调整要在弹出窗口中显示的最大项目数。

yourComboBox.setCellFactory(new Callback<ListView<String>, ListCell<String>>() {
        @Override
        public ListCell<String> call(ListView<String> param) {
            ListCell cell = new ListCell<String>() {
                @Override
                public void updateItem(String item, boolean empty) {
                    super.updateItem(item, empty);
                    int numItems = getListView().getItems().size();
                    int height = 175;    // set the maximum height of the popup
                    if (numItems <= 5) height = numItems * 35;    // set the height of the popup if number of items is equal to or less than 5
                    getListView().setPrefHeight(height);
                    if (!empty) {
                        setText(item.toString());
                    } else {
                        setText(null);
                    }
                }
            };
            return cell;
        }
    });

【讨论】:

    【解决方案2】:

    你可以使用两个JavaFx 列表。第一个是之前的com box list,另一个是final combo box list。然后您可以使用 yourCombo.getItems().setAll(Your List); 动态更改;

    这是我的示例代码:

    import java.util.ArrayList;
    import java.util.List;
    
    import javafx.application.Application;
    import javafx.scene.Scene;
    import javafx.scene.control.Button;
    import javafx.scene.control.ComboBox;
    import javafx.scene.layout.Region;
    import javafx.scene.layout.StackPane;
    import javafx.scene.layout.VBox;
    import javafx.stage.Stage;
    
    public class ComboBoxTest extends Application {
    
       @Override
       public void start(final Stage primaryStage) throws Exception {
    
          primaryStage.centerOnScreen();
          primaryStage.setHeight(200);
          primaryStage.setWidth(300);
    
          List<String> list1 = new ArrayList<>();
          list1.add("one");
          list1.add("two");
          list1.add("three");
    
          List<String> list2 = new ArrayList<>();
          list2.add("one");
          list2.add("two");
          list2.add("three");
          list2.add("four");
    
          final ComboBox<String> combo = new ComboBox<String>();
          combo.getItems().setAll(list1);
    
    
          Button button = new Button("Change combo contents");
          button.setOnAction(event -> {
             if ( combo.getItems().size() == 3 ) {
                combo.getItems().setAll(list2);
             } else {
                combo.getItems().setAll(list1);
             }
             combo.show();
          });
    
          VBox box = new VBox(20, combo, button );
          box.setMaxSize(Region.USE_PREF_SIZE, Region.USE_PREF_SIZE);
          primaryStage.setScene(new Scene( new StackPane(box) ));
    
          primaryStage.show();
    
       }
    
       public static void main(String[] args) throws Exception {
          launch(args);
       }
    
    } 
    

    【讨论】:

      【解决方案3】:

      我遇到了同样的问题,我用一个快速的技巧解决了它。 尝试显示并立即隐藏!

      add.setOnAction(new EventHandler<ActionEvent>() {
        @Override
        public void handle(ActionEvent event) {
          box.getItems().add("Item " + index++);
          box.getItems().add("Item " + index++);
          box.show();
          box.hide();
        }
      });
      

      【讨论】:

        【解决方案4】:

        试试这个:

        box.hide(); //before you set new visibleRowCount value
        box.setVisibleRowCount(rows); // set new visibleRowCount value
        box.show(); //after you set new visibleRowCount value
        

        它适用于我的可编辑组合框,我认为它适用于你的情况。

        【讨论】:

          【解决方案5】:

          您不必更改要显示的条目数。实现会自动处理。

          假设您最多要显示 10 个项目。然后,您使用 comboBox.setVisibleRowCount( 10 ); 如果任何时候少于 10 个项目,Javafx 将只显示与项目一样多的行。

          实际上,根据我的经验,在运行时更改可见行数有时会导致错误,所以最好只设置一个数字。

          希望对您有所帮助。


          我在理解问题所在时遇到了一些问题。我在下面做了一个简短的例子,你可以尝试一下,然后说出你想做的事情。

          public class Test extends Application{
          
              private int index = 0;
          
              @Override
              public void start(Stage primaryStage) throws IOException{
          
                  VBox vbox =  new VBox();    
                  vbox.setSpacing(10);
                  vbox.setAlignment(Pos.CENTER);
          
                  ComboBox<String> box = new ComboBox<>();
                  box.setPrefWidth(200);
                  box.setVisibleRowCount(10);
          
                  Button add = new Button("Add");
                  Button remove = new Button("Remove");
          
                  add.setOnAction(    new EventHandler<ActionEvent>() {
                      @Override
                      public void handle(ActionEvent event) {
                          box.getItems().add("Item " + index++);
                      }
                  });
          
          
                  remove.setOnAction( new EventHandler<ActionEvent>() {       
                      @Override
                      public void handle(ActionEvent event) {
                          if( index > 0 )
                              box.getItems().remove(--index);
                      }
                  });
          
          
                  vbox.getChildren().addAll(add, remove, box);
          
          
                  Scene scene = new Scene(vbox);
          
                  primaryStage.setScene(scene);
                  primaryStage.show();
              }
          
              public static void main(String[] args) {
                  launch(args);
              }
          
          }
          

          【讨论】:

          • 我试过了,它很接近,但不是我想要的 - setVisibleRowCount 设置最大行数,所以如果我将它设置为 1,它不会高​​于 1,但它不会t 设置行数,所以在我的场景中,如果我设置 2 个项目,然后设置 3 个项目,下拉菜单仍然会有一个滚动条......我想我在这里错过了一些非常基本的东西:-(
          • 稍微编辑了我的答案。检查出来然后返回:-)
          • 我正在尝试您的示例 - 它可以正常工作!当我单击添加时,它会添加一个元素并使下拉列表变大,当我单击“删除”时,它会删除一个元素并缩短下拉列表 - 应该如此,但在我的应用程序中,它没有,下拉高度大小与我插入的第一个值保持相同!,我试图找出你的应用程序和我的应用程序之间的差异,最引人注目的是我使用 FXML 文件,而你以编程方式绘制 GUI?
          • 是的,找到了!!!我的代码和你的不同之处在于你使用 box.add(或 box.remove),而我使用 box.setItems()。显然,当使用 setItems() 方法时,下拉高度不会更新,恕我直言,这是 JavaFX 中的错误吗?或者可能是故意的
          • 您想删除项目时是否使用了box.setItem("")?因为这可能是您的问题的原因。这实际上并没有删除任何项目,只是将它们设置为一个空白字符串。否则,我不确定,但我猜这是故意的,有点像使用 list.add、list.remove 和 list.set 时的情况
          猜你喜欢
          • 2019-11-20
          • 1970-01-01
          • 2013-11-03
          • 1970-01-01
          • 2016-12-16
          • 2011-03-30
          • 1970-01-01
          • 2021-05-03
          • 1970-01-01
          相关资源
          最近更新 更多