JavaFX 8:添加新Tab时的不稳定交互式TabPane

时间:2015-06-20 11:34:33

标签: java javafx javafx-8 tabpanel

我正在制作一个高度互动的TabPane,用于查看JavaFX 8中的联系人列表。为此,我创建了自己的Tab,EditableTab子类,它具有通过双击概述中的名称来更改选项卡名称的功能。当用户单击+号以创建新的联系人列表时,我希望程序创建一个新选项卡,选择它,然后聚焦名称并选择所有文本 - 一旦命名联系人列表是很自然的(类似于当你在Windows中创建一个新文件时)。

我的问题:这似乎很不稳定。大多数情况下,似乎出现了某种动画/转换问题,并且标签名称最终为空。以下是点击+按钮时通常但不总是的屏幕截图:screenshot

这就是我想要的:screenshot2

以下是我的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();
}  

}

1 个答案:

答案 0 :(得分:1)

以下是RenamableTab类的代码:

import javafx.application.Platform;
import javafx.scene.Node;
import javafx.scene.control.Label;
import javafx.scene.control.Tab;
import javafx.scene.control.TextField;

public class RenamableTab extends Tab {
    private final Label     label;
    private final TextField textField;

    public RenamableTab() {
        this("New Tab", null);
    }

    public RenamableTab(String text) {
        this(text, null);
    }

    public RenamableTab(String text, Node content) {
        super();
        label = new Label(text);
        textField = new TextField(text);
        setContent(content);
        textField.setStyle("-fx-background-color: transparent");
        setGraphic(label);
        label.setOnMouseClicked((mouseEvent) -> {
            if (mouseEvent.getClickCount() == 2) {
                rename();
            }
        });
        textField.setOnAction(event -> setGraphic(label));
        textField.focusedProperty().addListener((observable, oldValue, newValue) -> {
            if (!newValue) {
                label.setText(textField.getText());
                setGraphic(label);
            }
        });
    }

    public TextField getTextField() {
        return textField;
    }

    public void rename() {
        //textField.setPrefWidth(label.getWidth());
        //textField.setText(label.getText());
        setGraphic(textField);
        new Thread() {
            @Override
            public void run() {
                try {
                    Thread.sleep(300);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                Platform.runLater(new Runnable() {
                    @Override
                    public void run() {
                        textField.selectAll();
                        textField.requestFocus();
                    }
                });
            }
        }.start();
    }
}

这是FancyTabPane的代码:

import javafx.event.EventHandler;
import javafx.scene.control.Label;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.input.MouseEvent;

public class FancyTabPane extends TabPane {
    public FancyTabPane() {
        Tab newTabTab = new Tab();
        newTabTab.setClosable(false);
        Label addLabel = new Label("\u2795");
        addLabel.setOnMouseClicked(new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent paramT) {
                System.out.println("mouse click");
                addTab();
            }
        });
        /*
         * getSelectionModel().selectedItemProperty().addListener(new ChangeListener<Tab>() {
         * @Override
         * public void changed(ObservableValue<? extends Tab> paramObservableValue, Tab paramT1, Tab
         * paramT2) {
         * System.out.println("model");
         * if (paramT1 == newTabTab) {
         * System.out.println("tab");
         * addTab();
         * }
         * }
         * });
         */
        newTabTab.setGraphic(addLabel);
        getTabs().add(newTabTab);
    }

    public void addTab() {
        RenamableTab newTab = new RenamableTab();
        getTabs().add(getTabs().size() - 1, newTab);
        getSelectionModel().select(newTab);
        newTab.rename();
    }
}

当我选择了另一个标签时,我发布了新的标签按钮,不知道你是如何克服它的。