I use JavaFX and Scene Builder

There is a label, and a combobox with fonts. When choosing a font from a combobox, it is applied to the label. Work then the combobox works but is bad

1.When clicking on a combobox, the list of fonts does not open immediately, but after a second, as if the combobox is slowing down.

2.When the first font is selected, it is not applied to the label, and the use of the font only works if I click on the combobox again and select the font again, and not the one that was active.

How can you optimize the code so that everything works like a clock?

Maybe I did the wrong implementation of applying the font to the label.

Video

@FXML private ComboBox<String> fontSelector; @FXML private Label fontLabel; 

When clicking on the combobox, the method is called:

 public void changeLabel(ActionEvent event) { //apply selected font from combobox to label fontSelector.getSelectionModel().selectedItemProperty().addListener((obs, oldValue, newValue) -> fontLabel.setFont(Font.font(newValue, FontWeight.NORMAL, 35))); } //get system fonts ObservableList<String> fonts = FXCollections.observableArrayList(Font.getFamilies()); 

Further:

 @Override public void initialize(URL location, ResourceBundle resources) { //show fonts' actual look in combobox list fontSelector.setCellFactory((ListView<String> listView) -> { final ListCell<String> cell = new ListCell<>(){ @Override public void updateItem(String item, boolean empty) { super.updateItem(item, empty); if (item != null) { setText(item); setFont(new Font(item, 14)); } } }; return cell; }); fontSelector.setItems(fonts); } 

Editorial:

I changed the method that shows the system fonts in the combobox, but when I click on the combobox, the delay per second is still

 @FXML private ComboBox<Font> fontSelector; //get font family and size from comboboxes private static Font getFont(Font font, Integer size) { return Font.font(font == null ? null : font.getFamily(), size == null ? -1d : size.doubleValue()); } //getting font families fontSelector.getItems().addAll(Font.getFamilies().stream().map(name -> Font.font(name, 14)).toArray(Font[]::new)); // bind font based on size/family fontLabel.fontProperty() .bind(Bindings.createObjectBinding(() -> getFont(fontSelector.getValue(), size.getValue()), fontSelector.valueProperty(), size.valueProperty())); //display font families looks in combobox class FontListCell extends ListCell<Font> { @Override public void updateItem(Font item, boolean empty) { super.updateItem(item, empty); if (item != null) { setText(item.getFamily()); setFont(item); } else { setText(""); setFont(Font.font(12)); } } } fontSelector.setCellFactory(lv -> new FontListCell()); fontSelector.setButtonCell(new FontListCell()); } 

EDITOR 2:

I forgot to write that the problem is precisely in the display of the font family, that is, the names of the fonts, and not the font sizes.

    1 answer 1

    It is not necessary to add a listener every time a button is pressed. Usually they do it once and somewhere in advance.

    Here is a working example of using ComboBox:

     public class ComboBoxTest extends Application { public static void main(String[] args) { Application.launch(args); } @Override public void start(Stage stage) { Label fontLbl = new Label("Fonts:"); ComboBox<String> fontBox = new ComboBox<>(); fontBox.getItems().addAll("font1", "font2", "font3", "font4"); Label selectionLbl = new Label("current font"); // обработка нажатия ------------------------ fontBox.setOnAction(e->{ selectionLbl.setText(fontBox.getValue()); }); // ------------------------------------------ HBox row1 = new HBox(10, fontLbl, fontBox); VBox root = new VBox(row1, selectionLbl); root.setSpacing(10); Scene scene = new Scene(root, 300,300); stage.setScene(scene); stage.setTitle("Using ComboBox Controls"); stage.show(); } } 

    I add an example for this case:

     public class ComboBoxTest extends Application { public static void main(String[] args) { Application.launch(args); } @Override public void start(Stage stage) { Label fontLbl = new Label("Fonts:"); ComboBox<Font> fontBox = new ComboBox<>(); fontBox.getItems().addAll(new Font(10), new Font(12) , new Font(14) , new Font(16)); Label selectionLbl = new Label("current font"); // обработка нажатия ------------------------ fontBox.setOnAction(e->{ selectionLbl.setFont(fontBox.getValue()); }); // ------------------------------------------ HBox row1 = new HBox(10, fontLbl, fontBox); VBox root = new VBox(row1, selectionLbl); root.setSpacing(10); Scene scene = new Scene(root, 600,300); stage.setScene(scene); stage.setTitle("Using ComboBox Controls"); stage.show(); } } 
    • I made a revision, please look at your combobox string in your answer, and you added string font names, and how can you use system fonts in your example, and not string names? - kentforth
    • @kentforth Added font sample - Evgeniy Tkachenko
    • in your example you placed the font sizes. I also quite successfully implemented this, but I need to place in the Combobox the families of fonts that are in the system fonts folder on the computer, and that their names are reflected in the combobox - kentforth
    • @kentforth Then reformulate your question. Perhaps the task is more complicated than it seems to me, and therefore you have so much code - Evgeniy Tkachenko
    • did an editorial, maybe you know how to add your fonts from a folder to a combobox instead of system ones? this option would suit me too - kentforth 2:26 pm