最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

java - How to fix column width change in GridPane when selecting a value in ComboBox in JavaFX? - Stack Overflow

programmeradmin1浏览0评论

I have a form with 4 columns - label, control, label, control. The width of the label is unknown. I need the labels to always be fully displayed, meaning they should not be truncated, so only the width of the controls should change. If possible, I want the first and third columns (the ones with controls) to have the same width. So, column1Width should equal column3Width.

If I only use textfields, there is no issue. But when I added a stretching ComboBox and a value is selected in this ComboBox then column1Width != column3Width.

This is my code:

public class NewMain extends Application {

    enum Test { FOO, BAR }

    @Override
    public void start(Stage stage) {
        GridPane gridPane = new GridPane();
        gridPane.setHgap(10);
        gridPane.setVgap(10);
        gridPane.setPadding(new Insets(10));

        textFieldRow(gridPane, 0);
        textFieldRow(gridPane, 1);

        Label label1 = new Label("Label AAAAA BBBBB:");
        label1.setMinWidth(Region.USE_PREF_SIZE);
        var comboBox = new ComboBox<Test>();
        comboBox.setItems(FXCollections.observableArrayList(Test.values()));

        gridPane.add(label1, 0, 2);
        gridPane.add(comboBox, 1, 2);
        comboBox.setMaxWidth(Double.MAX_VALUE);

        Scene scene = new Scene(gridPane, 600, 200);
        stage.setScene(scene);
        stage.show();
    }

    private void textFieldRow(GridPane gridPane, int index) {
        Label label1 = new Label("Label AAAAA BBBBB:");
        label1.setMinWidth(Region.USE_PREF_SIZE);
        TextField textField1 = new TextField();
        GridPane.setHgrow(textField1, Priority.ALWAYS);
        textField1.setMinWidth(10);
        Label label2 = new Label("Label CCCCCC DDDDDD:");
        label2.setMinWidth(Region.USE_PREF_SIZE);
        TextField textField2 = new TextField();
        GridPane.setHgrow(textField2, Priority.ALWAYS);
        textField2.setMinWidth(10);

        gridPane.add(label1, 0, index);
        gridPane.add(textField1, 1, index);
        gridPane.add(label2, 2, index);
        gridPane.add(textField2, 3, index);
    }


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

And this is the result:

As you can see, at the beginning, everything works well. The width of column 1 is equal to the width of column 3. However, when a value is selected in the ComboBox, column 1 becomes wider than column 3.

Could anyone say how to fix it?

I have a form with 4 columns - label, control, label, control. The width of the label is unknown. I need the labels to always be fully displayed, meaning they should not be truncated, so only the width of the controls should change. If possible, I want the first and third columns (the ones with controls) to have the same width. So, column1Width should equal column3Width.

If I only use textfields, there is no issue. But when I added a stretching ComboBox and a value is selected in this ComboBox then column1Width != column3Width.

This is my code:

public class NewMain extends Application {

    enum Test { FOO, BAR }

    @Override
    public void start(Stage stage) {
        GridPane gridPane = new GridPane();
        gridPane.setHgap(10);
        gridPane.setVgap(10);
        gridPane.setPadding(new Insets(10));

        textFieldRow(gridPane, 0);
        textFieldRow(gridPane, 1);

        Label label1 = new Label("Label AAAAA BBBBB:");
        label1.setMinWidth(Region.USE_PREF_SIZE);
        var comboBox = new ComboBox<Test>();
        comboBox.setItems(FXCollections.observableArrayList(Test.values()));

        gridPane.add(label1, 0, 2);
        gridPane.add(comboBox, 1, 2);
        comboBox.setMaxWidth(Double.MAX_VALUE);

        Scene scene = new Scene(gridPane, 600, 200);
        stage.setScene(scene);
        stage.show();
    }

    private void textFieldRow(GridPane gridPane, int index) {
        Label label1 = new Label("Label AAAAA BBBBB:");
        label1.setMinWidth(Region.USE_PREF_SIZE);
        TextField textField1 = new TextField();
        GridPane.setHgrow(textField1, Priority.ALWAYS);
        textField1.setMinWidth(10);
        Label label2 = new Label("Label CCCCCC DDDDDD:");
        label2.setMinWidth(Region.USE_PREF_SIZE);
        TextField textField2 = new TextField();
        GridPane.setHgrow(textField2, Priority.ALWAYS);
        textField2.setMinWidth(10);

        gridPane.add(label1, 0, index);
        gridPane.add(textField1, 1, index);
        gridPane.add(label2, 2, index);
        gridPane.add(textField2, 3, index);
    }


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

And this is the result:

As you can see, at the beginning, everything works well. The width of column 1 is equal to the width of column 3. However, when a value is selected in the ComboBox, column 1 becomes wider than column 3.

Could anyone say how to fix it?

Share Improve this question asked Jan 18 at 11:03 SilverCubeSilverCube 6862 silver badges12 bronze badges 3
  • Don't you just need to bind the width property of the controls so that when the width of one changes, the width of the other is set to the same value? – Abra Commented Jan 18 at 11:29
  • @Abra I tried to use different bindings, but no one worked. – SilverCube Commented Jan 18 at 12:05
  • 3 This definitely seems like a JavaFX bug. A ComboBox’s preferred size should not change the first time (or any time) its item list is shown. – VGR Commented Jan 18 at 12:50
Add a comment  | 

1 Answer 1

Reset to default 0

I’m pretty sure this is a bug in JavaFX. It might or might not be related to this open bug, though the page says it only affects JavaFX 8 and 9.

As a workaround, you can create a subclass of ComboBox which never updates its preferred size unless the item list changes:

private static class ComboBoxWithSizeFix<T>
extends ComboBox<T> {
    private double fixedWidth;

    private final ListChangeListener<T> itemsListener = change -> {
        if (change.wasAdded() || change.wasRemoved()) {
            fixedWidth = 0;
        }
    };

    ComboBoxWithSizeFix() {
        itemsProperty().addListener((o, oldList, newList) -> {
            fixedWidth = 0;
            oldList.removeListener(itemsListener);
            newList.addListener(itemsListener);
        });

        getItems().addListener(itemsListener);
    }
    
    ComboBoxWithSizeFix(ObservableList<T> items) {
        super(items);

        itemsProperty().addListener((o, oldList, newList) -> {
            fixedWidth = 0;
            oldList.removeListener(itemsListener);
            newList.addListener(itemsListener);
        });

        getItems().addListener(itemsListener);
    }

    @Override
    protected double computePrefWidth(double height) {
        if (fixedWidth == 0) {
            fixedWidth = superputePrefWidth(height);
        }
        return fixedWidth;
    }
}
发布评论

评论列表(0)

  1. 暂无评论