2012-05-07 72 views
5

我是JavaFX 2的新手,對ComboBox和ListView的默認寬度感到困惑。我期望ComboBox更寬,所以文本「提示文本」將完全可見,因爲ListView我期望它更小,只有必要的寬度。代碼和屏幕截圖如下。JavaFX 2中的奇怪控制寬度?

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

回答

0

1)嘗試設置minWidth(x), prefWidth(x), maxWidth(x)。這有幫助,但不確定這是一個很好的決定。

2)從綁定框架使用方法void bind(ObservableValue<? extends Number> observable);。它是爲這種情況而開發的。例如:

someProperty.bind(otherProperty); 

也可以使用雙向綁定來鏈接它們。

+0

感謝您的回覆,maxWidth比舊的情況更方便/更好,但仍然需要猜測值):我需要一些由JavaFX完成的自動調整):謝謝屬性信息!真的很喜歡WPF ;-) –

+0

如果遇到這種情況,並且將fxml導出到您的項目中,最好使用SceneBuilder。 – 4lex1v

8

2)如何使兩個控件的寬度相同(因此兩個寬度中的最大值),是否可以在兩者的寬度之間創建某種鏈接?我特別尋找FXML的優雅解決方案。

它看起來像,默認情況下,ListView的maxWidth是無界的,但ComboBox的最大寬度被限制爲其初始項目列表的寬度。爲了使這些控件具有相同的寬度,最簡單的方法是將它們放在佈局管理器中(就像VBox一樣),然後鬆開comboBox的maxWidth。

在代碼中,你可以這樣做:

comboBox.setMaxWidth(Double.MAX_VALUE); 

在FXML添加attibute定義您的組合框元素如下:

maxWidth="Infinity" 

你可以用約翰·格雷的綁定解決方案,但我發現上面更優雅。

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,我相信推薦的方法,當你只是有幾個項目是放在一個垂直框您的項目,而不是使用一個ListView或ChoiceBox,而不是一個組合框,這樣你就不需要隨時佈局管理器和控件將爲您處理它,以進行單元格內省並隨時更新首選寬度。 ListView經過優化,可以處理虛擬化列表的情況,該列表可以包含數千個任意大小的項目,但您可能無法輕鬆計算佈局寬度,這就是爲什麼我認爲它帶有默認控件大小調整行爲將其尺寸調整到它可能具有的最小尺寸。通常,在使用ListView時,您只需爲listView選擇一個合理的prefWidth,並在listView上設置它,而不是如上例所示反思這些項目。

此外,你有一些提示文本被剪裁的圖像在我看來是JavaFX中的一個錯誤,它在ComboBox提示文本爲空時不能正確計算ComboBox控件的首選寬度比ComboBox項目文本更寬。由於ComboBox目前是一個全新的控件,而且我在JavaFX控件的早期版本中已經看到了這些問題,並且它們已經修復,所以我期望ComboBox的首選寬度計算將很快得到修復。

+0

非常感謝你解釋爲什麼控件的行爲如此(儘管我不明白爲什麼JavaFX在我看來是不直觀的)。設置MAX_VALUE是個不錯的主意,但問題仍然是要猜測vbox的正確寬度):[提供的代碼僅僅是一個簡短的例子] –

+0

已更新的答案可以更全面地回答問題和地址(某些)問題。 – jewelsea

+0

另一個更有趣的事情補充說SceneBuilder使用maxWidth =「 - Infinity」和「 - 」符號 – 4lex1v