JavaFX 2中的奇怪控制宽度?

时间:2012-05-07 19:59:52

标签: listview user-interface combobox size javafx-2

我是JavaFX 2的新手,对ComboBox和ListView的默认宽度感到困惑。我希望ComboBox更宽,所以文本“提示文本”将完全可见,对于ListView,我希望它更小,只有必要的宽。代码和截图如下。

1)我怎样才能实现ComboBox和Listview的大小和它们所需的宽度?

2)如何使两个控件的宽度相同(因此两个宽度中的最大值),是否可以在两者的宽度之间创建某种链接?我特别想为FXML寻找一个优雅的解决方案。

感谢任何提示!

@Override
public void start(Stage primaryStage) {
    ComboBox<String> comboBox = new ComboBox<String>();
    comboBox.setPromptText("the prompt text");
    ObservableList<String> items = FXCollections.observableArrayList();
    items.addAll("item 1", "item 2");
    comboBox.setItems(items);

    ListView<String> list = new ListView<String>();
    ObservableList<String> items2 =FXCollections.observableArrayList (
        "blue", "red");
    list.setItems(items2);

    VBox vBox = new VBox();
    vBox.getChildren().addAll(comboBox, list);

    primaryStage.setScene(new Scene(vBox, 200, 300));
    primaryStage.show();
}

enter image description here

2 个答案:

答案 0 :(得分:8)

  

2)如何使两个控件的宽度相同(因此两个宽度中的最大值),是否可以在两者的宽度之间创建某种链接?我特别想为FXML寻找一个优雅的解决方案。

默认情况下,ListView的maxWidth无限制,但是ComboBox将maxWidth限制为其初始项列表的宽度。要使这些控件具有相同的宽度,最简单的方法是将它们放在布局管理器中(如您所做的那样 - VBox)然后松开组合框的maxWidth。

在代码中,您可以这样做:

comboBox.setMaxWidth(Double.MAX_VALUE);

在FXML中,将以下属性定义添加到ComboBox元素:

maxWidth="Infinity"

您可以使用John Gray的绑定解决方案,但我发现上述更优雅。

  

1)我怎样才能实现ComboBox和Listview的大小和它们所需的宽度?

我认为你在这里问的是如何使组合框和列表视图只占用他们需要的空间,而不是更多。这是,我相信有点棘手,JavaFX平台并没有为此提供很多支持。

以下是一些示例代码,用于将列表框的大小固定为最低要求。

import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.scene.*;
import javafx.scene.control.ComboBox;
import javafx.scene.control.ListView;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Priority;
import javafx.stage.Stage;

public class GridControlWidths extends Application {
  public static void main(String[] args) throws Exception { launch(args); }
  @Override public void start(Stage stage) {
    ComboBox<String> comboBox = new ComboBox<String>(FXCollections.observableArrayList("item 1", "item 2"));
    comboBox.setPromptText("the prompt text");

    ListView<String> list = new ListView<String>(FXCollections.observableArrayList ("blue", "red"));

    // layout the controls in a grid with appropriate constraints.
    GridPane grid = new GridPane();
    grid.add(comboBox, 0, 0);
    grid.add(list, 0, 1);
    grid.setVgrow(list, Priority.ALWAYS);  // make the list grow vertically as much as possible

    // unclamp the max width of the combo box.
    comboBox.setMaxWidth(Double.MAX_VALUE);

    // display the scene.
    stage.setScene(new Scene(grid, 200, 300));
    stage.show();

    // set the prefWidth of the listview based on the list cells (allowing 8 pixels for padding of the cells).
    double maxWidth = 0;
    for (Node n: list.lookupAll(".text")) {
      maxWidth = Math.max(maxWidth, n.getBoundsInParent().getWidth() + 8);
    }
    list.setPrefWidth(maxWidth);
  }
}

FWIW,我相信当你只有一些项目时,推荐的方法是将你的项目放在VBox而不是使用ListView或ChoiceBox而不是ComboBox,这样你就不需要做单元格内省和更新首选宽度,因为布局管理器和控件将为您处理它。 ListView经过优化处理虚拟列表的情况,该列表可能包含数千个任意大小的项目,您可能无法轻松计算布局宽度,这就是为什么我认为它带有默认的控件大小调整行为将其大小调整到可能具有的最小尺寸。通常在使用ListView时,您只需为listView选择一个合理的prefWidth,并在listView上设置它,而不是像上面的例子那样内省项目。<​​/ p>

此外,你有一些提示文字被剪裁的图像(对我来说)似乎是JavaFX中的一个错误,当ComboBox提示文本较宽时,它无法正确计算ComboBox控件的首选宽度比ComboBox项目文本。由于ComboBox目前是一个全新的控件,我在JavaFX控件的早期版本中已经看到了这些问题,并且它们已得到修复,我希望ComboBox的首选宽度计算将很快得到合理修复。

答案 1 :(得分:0)

1)尝试设置minWidth(x), prefWidth(x), maxWidth(x)。这有帮助,但不确定这是一个好的决定。

2)使用绑定框架中的方法void bind(ObservableValue<? extends Number> observable);。它是为这种情况而开发的。例如:

someProperty.bind(otherProperty);

您也可以使用双向绑定来链接它们。