Описано поле со списком с изданием строку внизу, кнопка перезагрузки здесь не имеет значения.
Вся эта строка добавляется программно с использованием ComboBoxListViewSkin.
В этой строке находится рассматриваемая кнопка — тот Кнопка «+Добавить», работающая в тандеме с текстовым полем рядом с ней. Он становится активным, когда содержимое текстового поля не является пустым, и отключается, если оно пустое, в том числе сразу после отправки вновь созданной метки.
Минимальный воспроизводимый пример класса приложения:
Код: Выделить всё
package org.example;
import javafx.application.Application;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ComboBox;
import javafx.scene.control.TextField;
import javafx.scene.control.skin.ComboBoxListViewSkin;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class App extends Application {
@Override
public void start(Stage stage) throws Exception {
ComboBox comboBox = new ComboBox();
ComboBoxListViewSkin comboBoxListViewSkin = new ComboBoxListViewSkin(comboBox) {
private Button buttonAdd = new Button("+Add");
private TextField textField = new TextField();
private VBox pane = new VBox();
{
buttonAdd.setDisable(true);
buttonAdd.setOnAction(event -> {
String text = textField.getText();
if (text.isBlank()) return;
comboBox.getItems().add(text);
textField.clear();
buttonAdd.setDisable(true);
});
textField.setOnKeyTyped(event -> {
if (textField.getText().isBlank())
buttonAdd.setDisable(true);
else buttonAdd.setDisable(false);
});
textField.setOnAction(event -> buttonAdd.fire());
}
@Override
public Node getPopupContent() {
Node defaultContent = super.getPopupContent();
HBox hBox = new HBox();
hBox.getChildren().addAll(buttonAdd, textField);
HBox.setHgrow(textField, Priority.ALWAYS);
defaultContent.setManaged(true);
pane.getChildren().setAll(defaultContent, hBox);
return pane;
}
};
comboBox.setSkin(comboBoxListViewSkin);
comboBox.setPrefWidth(400);
comboBox.setPrefHeight(30);
VBox vBox = new VBox(comboBox);
Scene scene = new Scene(vBox, 400, 100);
stage.setScene(scene);
stage.show();
}
public static final void main(String[] args) {
launch(args);
}
}
Отмечу, что это изменение также правильно распространяется в структуру данных моего приложения, пользовательский интерфейс соответствующим образом обновляется, и, похоже, с программой не возникает никаких других проблем, за исключением этого цикла ошибок в журналах:
Код: Выделить всё
Exception in thread "JavaFX Application Thread" java.lang.StackOverflowError
at com.sun.glass.ui.Accessible$GetAttribute.run(Accessible.java:144)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
at com.sun.glass.ui.Accessible.lambda$getAttribute$0(Accessible.java:172)
at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:424)
at com.sun.glass.ui.Accessible.getAttribute(Accessible.java:169)
at com.sun.glass.ui.win.WinAccessible.sendNotification(WinAccessible.java:273)
at com.sun.glass.ui.win.WinAccessible.sendNotification(WinAccessible.java:281)
// ...
Похоже, что источником проблем является эта кнопкаAdd.setDisable(true ) в конце лямбда-выражения setOnAction, так как после его удаления ошибка больше не появляется.
Я не уверен, почему это вызывает проблему.
Я подумал, что, возможно, позвонив textField.clear() может вызвать собственный onAction и повторно активировать кнопку, но, похоже, это не так, и при этом он не зависает при повторном запуске onAction кнопки.
Редактировать:
Это происходит только при использовании кнопки напрямую щелчком мыши, а не при нажатии Enter в пределах текстовое поле (распространяемое buttonAdd.fire()).
Я использую JavaFX 19.0.2.1 в Windows 10 (22H2).
Подробнее здесь: https://stackoverflow.com/questions/792 ... rflowerror
Мобильная версия