Я делаю интерактивную TabPane для просмотра списков контактов в JavaFX 8. Для этого я создал свой собственный подкласс Tab, EditableTab, который имеет функции для изменения имени дважды щелкнув имя в обзоре. Когда пользователь нажимает знак + для создания нового списка контактов, я хочу, чтобы программа создала новую вкладку, выделила ее, затем сфокусировала имя и выделила весь текст - естественно назвать список контактов сразу (аналогично когда вы создаете новый файл в окнах).JavaFX 8: Нестабильная интерактивная TabPane при добавлении новой вкладки
Моя проблема: Это кажется очень неустойчивым. В большинстве случаев кажется, что возникает какая-то проблема анимации/перехода, а имя табуляции заканчивается пустым. Вот скриншот того, что обычно, но не всегда, происходит, когда кнопка + нажата:
И вот что я хочу:
Вот код для моего EditableTab:
public class EditableTab extends Tab {
private Label lbl;
private TextField txtField;
public EditableTab(String text, Node content) {
super();
setContent(content);
lbl = new Label(text);
txtField = new TextField(text);
txtField.setStyle("-fx-background-color: transparent");
setGraphic(lbl);
setupInteractivity();
}
public TextField getTextField() {
return txtField;
}
private void setupInteractivity() {
lbl.setOnMouseClicked((mouseEvent) -> {
if (mouseEvent.getClickCount() == 2) {
showTextField();
}
});
txtField.setOnAction(event -> setGraphic(lbl));
txtField.focusedProperty().addListener(
(observable, oldValue, newValue) -> {
if (! newValue) {
lbl.setText(txtField.getText());
setGraphic(lbl);
}
});
}
public void showTextField() {
txtField.setPrefWidth(lbl.getWidth());
txtField.setText(lbl.getText());
setGraphic(txtField);
txtField.selectAll();
txtField.requestFocus();
}
}
А вот код, в котором реализована функциональность:
private void addNewContactlist() {
Contactlist newList = new Contactlist();
newList.setName("New contact list");
contactlistApp.getContactlistData().add(newList);
ListView<Person> lv = new ListView<Person>(newList.getContacts());
setupListView(lv);
int position = tabPane.getTabs().size() - 1;
EditableTab tab = createEditableTab("New contact list", lv);
tabPane.getTabs().add(position, tab);
tabPane.getSelectionModel().select(tab);
tab.showTextField();
}
Я подозреваю, что проблема связана с некоторыми таймингами анимации/перехода, но это действительно просто догадка. Я попробовал обернуть showTextField()
звонок в Platform.runLater()
без везения.
Вот небольшой тест приложение, чтобы повторить вопрос:
public class TestApp extends Application {
TabPane tabPane = new TabPane();
@Override
public void start(Stage primaryStage) throws Exception {
Tab addNewContactlistTab = new Tab();
addNewContactlistTab.setClosable(false);
Label lbl = new Label("\u2795");
lbl.setOnMouseClicked(mouseEvent -> {
if (tabPane.getTabs().size() == 1) {
addNewTab();
}
});
addNewContactlistTab.setGraphic(lbl);
tabPane.getTabs().add(addNewContactlistTab);
addNewContactlistTab.selectedProperty().addListener(
(observable, oldValue, newValue) -> {
if (newValue && tabPane.getTabs().size() != 1) {
addNewTab();
}
});
Scene scene = new Scene(tabPane);
primaryStage.setScene(scene);
primaryStage.setWidth(600);
primaryStage.setHeight(400);
primaryStage.show();
}
private void addNewTab() {
int insertionIndex = tabPane.getTabs().size() - 1;
ListView<String> lv = new ListView<String>();
EditableTab tab = new EditableTab("Unnamed", lv);
tabPane.getTabs().add(insertionIndex, tab);
tabPane.getSelectionModel().select(tab);
tab.showTextField();
}
public static void main(String[] args) {
launch();
}
}
Спасибо! Однако, по крайней мере, на моем компьютере, это все равно не будет выбирать весь текст и готово TextField для редактирования. – TAsk
Это странно, я все еще работаю над этим. –
Действительно! Я склоняюсь к отказу от функциональности. Нажатие кнопки для переименования немедленно может повредить рабочий процесс. – TAsk