powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Java [игнор отключен] [закрыт для гостей] / javafx.scene.control.ComboBox
7 сообщений из 7, страница 1 из 1
javafx.scene.control.ComboBox
    #38388108
avp.mk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Сделал растягивающийся ComboBox. Назвал его StretchableComboBox.

Работает с ошибками:
1. Выпадающий список при первом открытии имеет очень маленький размер 48.0 x 28.0 (когда сам ComboBox имеет ширину более 200.0).
2. После первого открытия разер выпадающего списка не меняется (даже если изменился размер ComboBox'а).

Как бы примерно так (см. TreeItemMod.java) заставить его принять правильный размер?

StretchableComboBoxApp.java
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
package stretchablecomboboxapp;

import javafx.application.Application;
import static javafx.application.Application.launch;
import javafx.scene.Scene;
import javafx.stage.Stage;
import stretchablecomboboxapp.ui.MainPane;

public class StretchableComboBoxApp extends Application {

    @Override public void start(Stage stage) {
//        PlatformLogger layoutLogger = Logging.getLayoutLogger();
//        layoutLogger.setLevel(PlatformLogger.ALL);
        stage.setTitle("StretchableComboBox Test");
        stage.setScene(new Scene(new MainPane(stage), 300, 200));
        stage.show();
    }

    //<editor-fold defaultstate="collapsed" desc="main">
    public static void main(String[] args) { launch(args); }
    //</editor-fold>
}

MainPane.java
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
package stretchablecomboboxapp.ui;

import java.util.ArrayList;
import static javafx.collections.FXCollections.observableList;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.control.Button;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.HBoxBuilder;
import javafx.scene.layout.VBoxBuilder;
import javafx.stage.Stage;
import stretchablecomboboxapp.controls.ButtonMod;
import stretchablecomboboxapp.controls.StretchableComboBox;
import stretchablecomboboxapp.model.Obt;

public class MainPane extends BorderPane {

    //<editor-fold defaultstate="collapsed" desc="Отступы 5d">
    private static final double SPACING = 5;
    private static final Insets //
            PADDING = new Insets(SPACING),
            PADDING_VERTICAL = new Insets(SPACING, 0, SPACING, 0);
    //</editor-fold>
    //
    public final Stage stage;
    public final ObservableList<Obt> obts = observableList(new ArrayList<Obt>());
    public final StretchableComboBox<Obt> comboBoxObt = new StretchableComboBox<>(obts);
    
    public MainPane(Stage stage) {
        this.stage = stage;
        HBox hboxButtons = HBoxBuilder.create().spacing(5).padding(PADDING_VERTICAL).children(btAdd, btDelete).alignment(Pos.CENTER_RIGHT).build();
        setCenter(VBoxBuilder.create().spacing(5).padding(PADDING).children(comboBoxObt.wraper, hboxButtons).build());
    }

    private final Button btAdd = new ButtonMod("Добавить", new EventHandler<ActionEvent>() {
        int counterObt;
        @Override public void handle(ActionEvent e) {
            Obt obt = new Obt("Новый объект " + counterObt++);
            obts.add(obt);
            comboBoxObt.getSelectionModel().select(obt);
        }
    });

    private final Button btDelete = new ButtonMod("Удалить", new EventHandler<ActionEvent>() {
        @Override public void handle(ActionEvent e) {
            obts.removeAll(comboBoxObt.getValue());
            comboBoxObt.getSelectionModel().selectNext();
        }
    });
}

StretchableComboBox.java
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
package stretchablecomboboxapp.controls;

import java.lang.reflect.Method;
import javafx.collections.ObservableList;
import javafx.scene.control.ComboBox;
import javafx.scene.control.ComboBoxBase;
import javafx.scene.control.SingleSelectionModel;
import javafx.scene.layout.AnchorPane;

public class StretchableComboBox<T> extends ComboBox<T> {

    public StretchableComboBox(ObservableList<T> observableList) {
        super(observableList);
        forceResizeVirtualFlow();
    }

    public void selectItemOrNothing(T t) {
        SingleSelectionModel<T> selectionModel = getSelectionModel();
        if (getItems().contains(t)) {
            selectionModel.select(t);
        } else {
            selectionModel.clearAndSelect(0);
            selectionModel.clearSelection(0);
        }
    }

    //<editor-fold defaultstate="collapsed" desc="forceResizeVirtualFlow">
    public final void forceResizeVirtualFlow() {
        try {
            METHOD.invoke(this);
            System.out.println("invoked");
        } catch (Exception e) {
            System.out.println("Reflection doesn't work");
        }
    }
    private static final Method METHOD = getSomeMethod();

    private static Method getSomeMethod() {
        try {
//            Method method = Parent.class.getDeclaredMethod("clearSizeCache");
//            Method method = ComboBox.class.getDeclaredMethod("clearSizeCache");
//            Method method = Node.class.getDeclaredMethod("impl_pseudoClassStateChanged", String.class); //"showing"
            Method method = ComboBoxBase.class.getDeclaredMethod("чего б такого тут дёрнуть..");
            method.setAccessible(true);
            return method;
        } catch (NoSuchMethodException | SecurityException ex) {
            return null;
        }
    }
    //</editor-fold>
    //<editor-fold defaultstate="collapsed" desc="wraper">
    public final AnchorPane wraper = createAnchorPane();

    private AnchorPane createAnchorPane() {
        AnchorPane.setLeftAnchor(this, 0.0);
        AnchorPane.setRightAnchor(this, 0.0);
        AnchorPane anchorPane = new AnchorPane();
        anchorPane.getChildren().add(this);
        return anchorPane;
    }
    //</editor-fold>
}

ButtonMod.java
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
package stretchablecomboboxapp.controls;

import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.control.Button;

public class ButtonMod extends Button {

    public ButtonMod(String text, EventHandler<ActionEvent> onAction) {
        super(text);
        setOnAction(onAction);
    }
}

Obt.java
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
package stretchablecomboboxapp.model;

public class Obt {

    public String name;

    public Obt(String name) {
        this.name = name;
    }

    @Override public String toString() {
        return name;
    }
}

...
Рейтинг: 0 / 0
javafx.scene.control.ComboBox
    #38388184
avp.mk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
avp.mkПосле первого открытия ра м зер выпадающего списка не меняется (даже если изменился размер ComboBox'а).Иногда если открыть\закрыть выпадающий список размер может изменится.

В аттаче исходный код и скомпилированный пример.
...
Рейтинг: 0 / 0
javafx.scene.control.ComboBox
    #38390294
avp.mk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Нашёл условия при которых можно заставить выпадающий список принять правильный размер.
1ая проблема решена. 2ая иногда встречается (но редко).

StretchableComboBoxApp.java
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
package stretchablecomboboxapp;

import com.sun.javafx.Logging;
import com.sun.javafx.logging.PlatformLogger;
import javafx.application.Application;
import static javafx.application.Application.launch;
import javafx.scene.Scene;
import javafx.stage.Stage;
import stretchablecomboboxapp.ui.MainPane;

public class StretchableComboBoxApp extends Application {

    @Override public void start(Stage stage) {
//        PlatformLogger layoutLogger = Logging.getLayoutLogger();
//        layoutLogger.setLevel(PlatformLogger.ALL);
        stage.setTitle("StretchableComboBox Test");
        stage.setScene(new Scene(new MainPane(stage), 300, 200));
        stage.show();
    }

    //<editor-fold defaultstate="collapsed" desc="main">
    public static void main(String[] args) { launch(args); }
    //</editor-fold>
}

MainPane.java
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
package stretchablecomboboxapp.ui;

import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.control.Button;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.HBoxBuilder;
import javafx.scene.layout.VBoxBuilder;
import javafx.stage.Stage;
import stretchablecomboboxapp.controls.ButtonMod;
import stretchablecomboboxapp.controls.StretchableComboBox;
import stretchablecomboboxapp.model.Obt;

public class MainPane extends BorderPane {

    //<editor-fold defaultstate="collapsed" desc="Отступы 5d">
    private static final double SPACING = 5;
    private static final Insets //
            PADDING = new Insets(SPACING),
            PADDING_VERTICAL = new Insets(SPACING, 0, SPACING, 0);
    //</editor-fold>

    public final Stage stage;
    public final ObservableList<Obt> obts = FXCollections.observableArrayList();
    public final StretchableComboBox<Obt> comboBoxObt = new StretchableComboBox<>(obts, new Obt("stub"));

    public MainPane(Stage stage) {
        this.stage = stage;
        HBox hboxButtons = HBoxBuilder.create().spacing(5).padding(PADDING_VERTICAL).children(btAdd, btDelete).alignment(Pos.CENTER_RIGHT).build();
        setCenter(VBoxBuilder.create().spacing(5).padding(PADDING).children(comboBoxObt.wraper, hboxButtons).build());
    }

    private final Button btAdd = new ButtonMod("Добавить", new EventHandler<ActionEvent>() {
        int counterObt;
        @Override public void handle(ActionEvent e) {
            Obt obt = new Obt("Новый объект " + counterObt++);
            obts.add(obt);
            comboBoxObt.getSelectionModel().select(obt);
        }
    });

    private final Button btDelete = new ButtonMod("Удалить", new EventHandler<ActionEvent>() {
        @Override public void handle(ActionEvent e) {
            obts.removeAll(comboBoxObt.getValue());
            comboBoxObt.getSelectionModel().selectNext();
        }
    });
}

StretchableComboBox.java
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
package stretchablecomboboxapp.controls;

import javafx.collections.ObservableList;
import javafx.scene.control.ComboBox;
import javafx.scene.layout.AnchorPane;

public class StretchableComboBox<T> extends ComboBox<T> {

    public StretchableComboBox(ObservableList<T> observableList, T stub) {
        super(observableList);
        this.stub = stub;
    }

    //<editor-fold defaultstate="collapsed" desc="dummy resize on layoutChildren">
    private final T stub;

    @Override protected void layoutChildren() {
        super.layoutChildren();

        ObservableList<T> items = getItems();
        items.add(stub);
        items.remove(stub);

        show();
        hide();
    }
    //</editor-fold>

    //<editor-fold defaultstate="collapsed" desc="wraper">
    public final AnchorPane wraper = createAnchorPane();

    private AnchorPane createAnchorPane() {
        AnchorPane.setLeftAnchor(this, 0.0);
        AnchorPane.setRightAnchor(this, 0.0);
        AnchorPane anchorPane = new AnchorPane();
        anchorPane.getChildren().add(this);
        return anchorPane;
    }
    //</editor-fold>
}

ButtonMod.java
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
package stretchablecomboboxapp.controls;

import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.control.Button;

public class ButtonMod extends Button {

    public ButtonMod(String text, EventHandler<ActionEvent> onAction) {
        super(text);
        setOnAction(onAction);
    }
}

Obt.java
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
package stretchablecomboboxapp.model;

public class Obt {

    public String name;

    public Obt(String name) {
        this.name = name;
    }

    @Override public String toString() {
        return name;
    }
}

...
Рейтинг: 0 / 0
javafx.scene.control.ComboBox
    #38390871
avp.mk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Улучшил (теперь используется reflection). 2ая проблема практически ушла (можно даже сказать полностью..). Но все равно пока нет непосредственного вызова пересчёта размера выпадающего списка (как было задумано).

Смотрим, комментируем. Любая критика приветствуется.

MainPane.java (почти не изменился)
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
package stretchablecomboboxapp.ui;

import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.control.Button;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.HBoxBuilder;
import javafx.scene.layout.VBoxBuilder;
import javafx.stage.Stage;
import stretchablecomboboxapp.controls.ButtonMod;
import stretchablecomboboxapp.controls.StretchableComboBox;
import stretchablecomboboxapp.model.Obt;

public class MainPane extends BorderPane {

    //<editor-fold defaultstate="collapsed" desc="Отступы 5d">
    private static final double SPACING = 5;
    private static final Insets //
            PADDING = new Insets(SPACING),
            PADDING_VERTICAL = new Insets(SPACING, 0, SPACING, 0);
    //</editor-fold>
    //
    public final Stage stage;
    public final ObservableList<Obt> obts = FXCollections.observableArrayList();
    public final StretchableComboBox<Obt> comboBoxObt = new StretchableComboBox<>(obts);

    public MainPane(Stage stage) {
        this.stage = stage;
        HBox hboxButtons = HBoxBuilder.create().spacing(5).padding(PADDING_VERTICAL).children(btAdd, btDelete).alignment(Pos.CENTER_RIGHT).build();
        setCenter(VBoxBuilder.create().spacing(5).padding(PADDING).children(comboBoxObt.wraper, hboxButtons).build());
    }

    private final Button btAdd = new ButtonMod("Добавить", new EventHandler<ActionEvent>() {
        int counterObt;
        @Override public void handle(ActionEvent e) {
            Obt obt = new Obt("Новый объект " + counterObt++);
            obts.add(obt);
            comboBoxObt.getSelectionModel().select(obt);
        }
    });

    private final Button btDelete = new ButtonMod("Удалить", new EventHandler<ActionEvent>() {
        @Override public void handle(ActionEvent e) {
            obts.removeAll(comboBoxObt.getValue());
            comboBoxObt.getSelectionModel().selectNext();
        }
    });
}

StretchableComboBox.java
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
package stretchablecomboboxapp.controls;

import com.sun.javafx.collections.ListListenerHelper;
import com.sun.javafx.collections.NonIterableChange;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import javafx.beans.property.ReadOnlyBooleanWrapper;
import javafx.collections.ObservableList;
import javafx.scene.control.ComboBox;
import javafx.scene.control.ComboBoxBase;
import javafx.scene.layout.AnchorPane;

public class StretchableComboBox<T> extends ComboBox<T> {

    public StretchableComboBox(ObservableList<T> observableList) {
        super(observableList);
    }

    @Override
    protected void layoutChildren() {
        super.layoutChildren();
        fireValueChanged(getItems());
        invokeChangeShowingProperty();
    }
    //
    //<editor-fold defaultstate="collapsed" desc="fireValueChanged">
    private ObservableList prevObservableList;
    private ListListenerHelper prevListenerHelper;

    private void fireValueChanged(ObservableList observableList) {
        try {
            if (prevObservableList != observableList) {
                //подразумевается что observableList - экземрляр com.sun.javafx.collections.ObservableListWrapper
                Field field = observableList.getClass().getDeclaredField("listenerHelper");
                field.setAccessible(true);
                prevListenerHelper = (ListListenerHelper) field.get(observableList);
                prevObservableList = observableList;
            }

            ListListenerHelper.fireValueChangedEvent(prevListenerHelper,
                    new NonIterableChange.SimpleUpdateChange(observableList.size(), observableList));
        } catch (Exception e) {
            System.out.println("Reflection doesn't work (fireValueChanged didn't invoked) " + e.getMessage());
        }
    }
    //</editor-fold>
    //
    //
    //<editor-fold defaultstate="collapsed" desc="method showingPropertyImpl">
    private void invokeChangeShowingProperty() {
        try {
            ReadOnlyBooleanWrapper property = (ReadOnlyBooleanWrapper) METHOD_SHOWING_PROPERTY_IMPL.invoke(this);
            property.set(true);
            property.set(false);
        } catch (Exception e) {
            System.out.println("Reflection doesn't work (showingPropertyImpl didn't invoked)");
            show();
            hide();
        }
    }
    //
    private static final Method METHOD_SHOWING_PROPERTY_IMPL = getMethodShowingPropertyImpl();

    private static Method getMethodShowingPropertyImpl() {
        try {
            Method method = ComboBoxBase.class.getDeclaredMethod("showingPropertyImpl");
            method.setAccessible(true);
            return method;
        } catch (NoSuchMethodException | SecurityException ex) {
            return null;
        }
    }
    //</editor-fold>
    //
    //
    //<editor-fold defaultstate="collapsed" desc="wraper">
    public final AnchorPane wraper = createAnchorPane();

    private AnchorPane createAnchorPane() {
        AnchorPane.setLeftAnchor(this, 0.0);
        AnchorPane.setRightAnchor(this, 0.0);
        AnchorPane anchorPane = new AnchorPane();
        anchorPane.getChildren().add(this);
        return anchorPane;
    }
    //</editor-fold>
}

...
Рейтинг: 0 / 0
javafx.scene.control.ComboBox
    #38438316
avp.mk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
В джаве 8 (EA) не работает. Как можно в oracle этот баг засабмитить? (чтобы в релизе его не было)
...
Рейтинг: 0 / 0
javafx.scene.control.ComboBox
    #38438354
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
...
Рейтинг: 0 / 0
javafx.scene.control.ComboBox
    #38438358
avp.mk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Blazkowicz, спасибо.
...
Рейтинг: 0 / 0
7 сообщений из 7, страница 1 из 1
Форумы / Java [игнор отключен] [закрыт для гостей] / javafx.scene.control.ComboBox
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]