-4

Question

My dropdown list of the CheckComboBox expands to the size of the largest element entered in it, but I want to limit its width so it doesn't get larger than the screen width.


Library Information

org.​controlsfx.​control.CheckComboBox

---------------------
| CheckComboBox | V |
--------------------------------------------
| "Long item 1 Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. (Out of screen bounds)|
--------------------------------------------
| "Long item 2"                              |
 --------------------------------------------
| "Long item 3"                              |
 --------------------------------------------

As you can notice, the item 1 text is really long in length. In this StackOverflow topic, it maintains the width and adds a new line. In JavaFX, it goes out of bounds: the width is bigger than the screen width size.

How do I fix this? How Do I limit the width to either the window width or the stage width or at least the screen width? Or even to the ComboBox width, like in this image below:

'CheckComboBox Dropdown' has the same width of the 'CheckComboBox'

Reproducible example

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;
import org.controlsfx.control.CheckComboBox;

public class Main2 extends Application {

    @Override
    public void start(Stage stage) {

        Pane root = new Pane();

        CheckComboBox<String> box = new CheckComboBox<>();
        double width = 200;
        box.setMinWidth(width);
        box.setPrefWidth(width);
        box.setMaxWidth(width);

        String item1 = new String("short name");
        String item2 = new String("Pellentesque habitant morbi tristique senectus et netus et " +
                "malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, " +
                "ultricies eget, tempor sit amet, ante.Pellentesque habitant morbi tristique senectus et netus et " +
                "malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, " +
                "ultricies eget, tempor sit amet, ante.");
        String item3 = new String("short name again");

        box.getItems().setAll(item1, item2, item3);
        root.getChildren().add(box);

        stage.setScene(new Scene(root, 300, 50));
        stage.show();
    }

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

References

In the topic, this issue is addressed, but with a few differences. The main difference is that, in my case, I use a CheckComboBox from ControlsFx instead of a 'simple' ComboBox from JavaFX. The second difference is that CheckComboBox doesn't have a setCellFactory method.

PS: Im not recompiling a library for something simple as this. If the problem can onlu be solved by recompiling the library, then its not a solution I want. You can keep giving -1, good luck with it.

KenobiBastila
  • 539
  • 4
  • 16
  • 52
  • 1
    the clean solution is a custom skin to size the dropdown independently from the size requirements of the button/textfield. Short of that, you _might_ (or not, don't remember if that's really possible) get away with a onShown handler that resizes the dropDown as needed (onShowing would be better, but most probably is too early) – kleopatra Jul 25 '20 at 15:21
  • 1
    anyway, it's open source (which implies that you _do have_ the source) - find where the sizing is done, change to your own requirements and recompile .. – kleopatra Jul 25 '20 at 15:23
  • 1
    Maybe _line 101_ in [CheckComboBoxSkin.java](https://github.com/controlsfx/controlsfx/blob/0889a9608b75da7b734fbecd98ea36d86e84bc94/controlsfx/src/main/java/impl/org/controlsfx/skin/CheckComboBoxSkin.java) has to be changed?! – anko Jul 25 '20 at 15:59
  • 1
    @anko I think you are right. Im going to try that, I think you should post that as a solution if it works so I can properly reward you for answering :) – KenobiBastila Jul 25 '20 at 17:00
  • 1
    I am not able to recompile the controlsfx-master so i can't test it. If you manage to get it to work, then please write an answer yourself as my reward. :P – anko Jul 25 '20 at 17:28
  • you already know how to solve it - go ahead, implement a custom skin and come back with a [mcve] when stuck – kleopatra Jul 27 '20 at 21:37

1 Answers1

-1

There must be a better way, but maybe it is enough for your project to just override the items toString() method ("quick and dirty")?! Here is a small example what i mean:

App:

package test;

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;
import org.controlsfx.control.CheckComboBox;


public class App extends Application {

    @Override
    public void start(Stage stage) {

        Pane root = new Pane();

        CheckComboBox<Item> box = new CheckComboBox<>();
        double width = 200;
        box.setMinWidth(width);
        box.setPrefWidth(width);
        box.setMaxWidth(width);

        Item item1 = new Item("short name");
        Item item2 = new Item("Pellentesque habitant morbi tristique senectus et netus et " +
                "malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, " +
                "ultricies eget, tempor sit amet, ante.");
        Item item3 = new Item("short name again");

        box.getItems().setAll(item1, item2, item3);
        root.getChildren().add(box);

        stage.setScene(new Scene(root, 300, 50));
        stage.show();
    }

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

Item class:

package test;

import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;

public class Item {

    private final StringProperty name = new SimpleStringProperty("");

    public Item(String name) {
        this.name.set(name);
    }

    @Override
    public String toString() {
        // Show max 20 characters:
        int maxLength = 20;
        if (getName().length() > maxLength)
            return getName().substring(0, maxLength - 3).concat("...");
        return getName();
    }

    public String getName() {
        return name.get();
    }

    public StringProperty nameProperty() {
        return name;
    }

    public void setName(String name) {
        this.name.set(name);
    }
}

Preview:

enter image description here

anko
  • 1,628
  • 1
  • 6
  • 14
  • 1
    no, overriding toString for application reasons is always wrong ;) – kleopatra Jul 25 '20 at 15:18
  • 2
    _a good alternative_ because it's not ;) Doing so (and relying on it) will break the view in tons of ways, f.i.: show in different controls, change the node width, change localization, show another property, .. Repeating: it's plain wrong even for a quick-and-dirty approach. – kleopatra Jul 27 '20 at 10:05