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

我的问题:这似乎非常不稳定。在大多数情况下,似乎会出现某种动画/过渡问题,并且选项卡名称最终为空。这是单击+按钮通常但并非总是发生的屏幕截图:

这就是我想要的:

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


}

最佳答案

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


当选择了另一个标签时,我已经发出了新标签按钮,但不确定如何克服。

关于java - JavaFX 8:添加新的Tab时不稳定的交互式TabPane,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/30953502/

10-10 06:03