如何解决组合框的冲突?

How to resolve conflict of comboboxes?

我正在使用 JavaFX 和 Scene Builder 制作应用程序。

-我有一个选择字体大小的组合框(id - size)

-我有一个用于选择字体系列的组合框(id - 字体选择器)

-我有一个标签(id-前面的标签)

Problem #1: When I I click on Combobox with fThe drop-down. Drop-down list appears only after a second. It seems like it works slow

Problem #2: When I click on combobox with font family and choose some font it doesn't apply to the label, but font family applies when I click on combobox and choose font second time. In this case, I should pick a font two times in a row to apply a font to my label

Problem a #3(Main problem): I have conflict of comboboxes. When I choose a font family it applies to the label, but when I choose font size from other combobox size also applies but after that font family of the label become default. Same situation occurs when I pick font size and then pick font family from other combobox.

似乎只能将一个组合框应用于标签。

如何解决这些问题?

*All code is in the Controller

*Problem #3 is the primordial one.

Video

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

//create array of font sizes
ObservableList<Integer> fontSizes = FXCollections.observableArrayList(8, 
10, 11, 12, 14, 16, 18, 20, 24, 30, 36, 40, 48, 60, 72);

//get fonts from system
ObservableList<String> fonts = 
FXCollections.observableArrayList(Font.getFamilies());

//getting Controller variables and methods through Context class
Controller cont = Context.getInstance().getController();


@Override
public void initialize(URL location, ResourceBundle resources) {

//register FontController in  Context Class
Context.getInstance().setFontController(this);

 //bind text from textfield to label
 fontLabel.textProperty().bind(fontTextfield.textProperty());


 //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);
size.setItems(fontSizes);
size.setOnAction(e -> updateFontSize());
}

将字体大小应用于组合框标签的方法

private void updateFontSize() {
fontLabel.setFont(Font.font(size.getValue()));
}

将组合框的字体系列应用到标签的方法

public void changeLabel(ActionEvent event) {    
fontSelector.getSelectionModel().selectedItemProperty().addListener((obs, 
oldValue, newValue) -> fontLabel.setFont(Font.font(newValue, 
FontWeight.NORMAL, 35)));
}

编辑:

我假设组合框的冲突出现在这里:

fontSelector.getSelectionModel().selectedItemProperty().addListener((obs, 
oldValue, newValue) -> fontLabel.setFont(Font.font(newValue, 
FontWeight.NORMAL, 35)));

如何重构那行代码以使其工作但在 FontWeight.Normal 括号后没有具体的字体大小?

这不是组合框冲突。发生的事情正是您编写的代码。

通过阅读 Font.font( size )javadoc :

Searches for an appropriate font based on the default font family name and given font size.

其实问题很简单。改变方法

private void updateFontSize() {
   // Here we retrieve the current font family name in order to not apply the default one.
   fontLabel.setFont(Font.font(fontLabel.getFont().getName(), size.getValue()));
}

改字体族名也是一样的道理。检索标签字体的大小并应用具有以前字体大小的新字体系列名称。

您需要组合 ComboBoxes 的两个值来创建字体。不过,您每个人只使用一个。至于打开字体ComboBox时的延迟:这可能是因为需要加载多个Font造成的。您可以替换 ComboBox 类型参数 Font 并预加载字体。

要对 ComboBox 按钮区域中的字体也使用自定义显示,您需要将 cellFactory 创建的单元格类型设置为 buttonCell

使用基于 ComboBoxes 的 2 value 属性的字体绑定

例子

private static Font getFont(Font font, Integer size) {
    return Font.font(font == null ? null : font.getFamily(), size == null ? -1d : size.doubleValue());
}

@Override
public void start(Stage primaryStage) throws Exception {
    ComboBox<Font> fontSelector = new ComboBox<>();
    fontSelector.getItems().addAll(Font.getFamilies().stream().map(name -> Font.font(name, 14)).toArray(Font[]::new));

    ComboBox<Integer> size = new ComboBox<>();
    size.getItems().addAll(10, 11, 12, 14, 16, 18, 20, 24, 30, 36, 40, 48, 60, 72);

    Label fontLabel = new Label("Hello World");
    
    // bind font based on size/family
    fontLabel.fontProperty()
            .bind(Bindings.createObjectBinding(() -> getFont(fontSelector.getValue(), size.getValue()),
                    fontSelector.valueProperty(), size.valueProperty()));

    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(14));
            }
        }
    }
    
    fontSelector.setCellFactory(lv -> new FontListCell());
    fontSelector.setButtonCell(new FontListCell());

    Scene scene = new Scene(new VBox(fontSelector, size, fontLabel), 300, 500);
    primaryStage.setScene(scene);
    primaryStage.show();
}