B4J Question ComboBox cell item (a label) disappears when selected

TelKel81

Active Member
Licensed User
The label is only visible again if I scroll out then back in view.

B4X:
Dim cbox as ComboBox

cbox.Initialize("")

For Each FontFamilyName As String In fx.GetAllFontFamilies
        Dim font As Font = fx.CreateFont(FontFamilyName, 16, False, False)
        Dim lbl As Label
        lbl.Initialize("lbl")
        lbl.Text = fontFamilyName
        cbox.Items.Add(lbl)
    Next

Image 1) Before selection
Image 2) After selection.

1678328383058.png
1678328385988.png


However, the solution is literally in the API documentation (see below). But it implies a method override. How to approach this in B4J ? I don't mind using a workaround for this.

------------------------------------------------------------------------------------------
The recommended approach, rather than inserting Node instances into the items list, is to put the relevant information into the ComboBox, and then provide a custom cell factory. For example, rather than use the following code:

ComboBox<Rectangle> cmb = new ComboBox<>();
cmb.getItems().addAll(
new Rectangle(10, 10, Color.RED),
new Rectangle(10, 10, Color.GREEN),
new Rectangle(10, 10, Color.BLUE));}
You should do the following:

ComboBox<Color> cmb = new ComboBox<>();
cmb.getItems().addAll(
Color.RED,
Color.GREEN,
Color.BLUE);

cmb.setCellFactory(p -> {
return new ListCell<>() {
private final Rectangle rectangle;
{
setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
rectangle = new Rectangle(10, 10);
}

@override protected void updateItem(Color item, boolean empty) {
super.updateItem(item, empty);

if (item == null || empty) {
setGraphic(null);
} else {
rectangle.setFill(item);
setGraphic(rectangle);
}
}
};
});
 
Solution
Solved by using inline Java notably to override the UpdateItem method of the ComboBoxListCell class :

Java:
#If Java
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Label;
import javafx.scene.control.ListCell;
import javafx.scene.text.Font;

public void LoadComboBoxFontItems(ComboBox cbox) {

    ObservableList<Font> fontList = FXCollections.observableArrayList();
    for (String fontFamily : Font.getFamilies()) {
        fontList.add(Font.font(fontFamily, Font.getDefault().getSize()));
    }
    cbox.setItems(fontList);

    cbox.setCellFactory(listView -> new ListCell<Font>() {
       private final Label label = new Label()...

teddybear

Well-Known Member
Licensed User
The label is only visible again if I scroll out then back in view.

B4X:
Dim cbox as ComboBox

cbox.Initialize("")

For Each FontFamilyName As String In fx.GetAllFontFamilies
        Dim font As Font = fx.CreateFont(FontFamilyName, 16, False, False)
        Dim lbl As Label
        lbl.Initialize("lbl")
        lbl.Text = fontFamilyName
        cbox.Items.Add(lbl)
    Next

Image 1) Before selection
Image 2) After selection.

View attachment 140063View attachment 140064
You should add text instead of label.
B4X:
 cbox.Items.Add(fontFamilyName)
 
Last edited:
Upvote 0

TelKel81

Active Member
Licensed User
I'm sorry I forgot the line of code where I set the font of the label to the corresponding font family name (as seen in the images).
So I do need the label.
 
Upvote 0

teddybear

Well-Known Member
Licensed User
I'm sorry I forgot the line of code where I set the font of the label to the corresponding font family name (as seen in the images).
So I do need the label.
I wonder what you do using the label. why not you do that(the label you need) in event SelectedIndexChanged
 
Last edited:
Upvote 0

TelKel81

Active Member
Licensed User
I set a font to the label :
lbl.Font = Font.ToNativeFont
The reason is to let the user immediately evaluate/select the font style that he wants as he scrolls through the list.
 
Upvote 0

teddybear

Well-Known Member
Licensed User
I set a font to the label :
lbl.Font = Font.ToNativeFont
The reason is to let the user immediately evaluate/select the font style that he wants as he scrolls through the l
It is irrelevant to the label, the font is in cbox not the label you arranged, you should set the cbox Style in SelectedIndexChanged event
B4X:
private sub cbox_SelectedIndexChanged(index as int, Value as Object)
cbox.Style=$"-fx-font-family:'${Value}'"$
End sub
 
Last edited:
Upvote 0

TelKel81

Active Member
Licensed User
Have you seen the 2 images in my first post ?
Every item in the combobox list displays the family name of the font, and also that item has the actual font of that font family name.
That's why I put labels instead of just strings. As you already know, strings don't have fonts attached to them.
My app is for creating image / text special effects.
 
Upvote 0

teddybear

Well-Known Member
Licensed User
Have you seen the 2 images in my first post ?
Every item in the combobox list displays the family name of the font, and also that item has the actual font of that font family name.
That's why I put labels instead of just strings. As you already know, strings don't have fonts attached to them.
My app is for creating image / text special effects.
I got it, you need to customize a combo box instead of using the combobox view, I think it is not diffcult to use custumlistvew doing what you want
 
Upvote 0

TelKel81

Active Member
Licensed User
Solved by using inline Java notably to override the UpdateItem method of the ComboBoxListCell class :

Java:
#If Java
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Label;
import javafx.scene.control.ListCell;
import javafx.scene.text.Font;

public void LoadComboBoxFontItems(ComboBox cbox) {

    ObservableList<Font> fontList = FXCollections.observableArrayList();
    for (String fontFamily : Font.getFamilies()) {
        fontList.add(Font.font(fontFamily, Font.getDefault().getSize()));
    }
    cbox.setItems(fontList);

    cbox.setCellFactory(listView -> new ListCell<Font>() {
       private final Label label = new Label();

       @Override
       protected void updateItem(Font font, boolean empty)
        {
           super.updateItem(font, empty);
           if (font == null || empty) {
               setGraphic(null);
           } else {
               label.setText(font.getFamily());
               label.setFont(font);
               setGraphic(label);
           }
       }
    });

    cbox.setButtonCell(new ListCell<Font>() {
        @Override
        protected void updateItem(Font font, boolean empty) {
           super.updateItem(font, empty);
           if (font == null || empty) {
               setText("");
           } else {
               setText(font.getFamily());
            }
        }
    });
}
#End If
 
Upvote 0
Solution
Top