JavaFX TabPane选项卡不会更新位置

时间:2017-12-03 07:25:01

标签: java javafx tabs javafx-2 tabpanel

我注意到在TabPane添加和删除标签时,它无法匹配基础列表中标签顺序的位置。仅当父级的宽度完全隐藏至少一个选项卡时才会发生这种情况。这里有一些复制问题的代码:

public class TabPaneTester extends Application {
    @Override
    public void start(Stage primaryStage) throws Exception {
        Scene scene = sizeScene();
        primaryStage.setMinHeight(200);
        primaryStage.setWidth(475);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    private Scene sizeScene(){
        TabPane tabPane = new TabPane();
        tabPane.setTabMinWidth(200);
        tabPane.getTabs().addAll(newTabs(3));
        Scene scene = new Scene(tabPane);
        scene.setOnKeyPressed(e -> tabPane.getTabs().add(1, tabPane.getTabs().remove(0)));
        return scene;
    }

    private static Tab[] newTabs(int numTabs){
        Tab[] tabs = new Tab[numTabs];
        for(int i = 0; i < numTabs; i++) {
            Label label = new Label("Tab Number " + (i + 1));
            Tab tab = new Tab();
            tab.setGraphic(label);
            tabs[i] = tab;
        }
        return tabs;
    }

    public static void main(String[] args) {
        launch();
    }

}

当您按某个键时,它会删除第一个标签(在索引0处)并将其放回索引1,从而有效地交换前两个标签。但是,在运行时,标签实际上不会在视觉上交换(即使标签切换器菜单 切换其位置)。

Tab position off

如果您更改屏幕的宽度以包括隐藏的第三个选项卡的像素(用500替换475),它将按预期工作。关于如何解决这个问题的任何线索?

1 个答案:

答案 0 :(得分:2)

这确实是一个错误,我无法在公共JIRA中报告现在报告https://bugs.openjdk.java.net/browse/JDK-8193495

如果你想亲眼看看,我所有的分析都是基于TabPaneSkin中的代码。

摘要

当您删除然后添加标签时,问题就出现了#34;太快了#34;删除选项卡时,在删除过程中进行异步调用。如果您进行了其他更改,例如在异步调用完成之前添加选项卡(或至少&#34;完成足够的&#34;),则更改过程会将窗格视为无效状态。

详细信息

删除标签removeTabs,如下所示:

  1. 调用各种内部删除方法。
  2. 然后检查是否应该设置关闭动画。
    • 如果是(GROW),
      1. 动画将对requestLayout方法的调用排队,该方法本身是异步调用的,
      2. 并且动画开始(异步)并且方法返回。
    • 如果不是(NONE),
        立即调用
      1. requestLayout,方法返回。
  3. 窗格处于无效状态的时间是从调用返回到requestLayout返回的时间(在另一个线程上)。此持续时间相当于requestLayout的持续时间加上动画的持续时间(如果有的话),即ANIMATION_SPEED = 150 [ms]。在此期间调用addTabs会导致意外的影响,因为正确添加选项卡所需的数据尚未准备就绪。

    解决方法

    在通话之间添加一个人工暂停:

    ObservableList<Tab> tabs = tabPane.getTabs();
    PauseTransition p = new PauseTransition(Duration.millis(150 + 20));
    scene.setOnKeyPressed(e -> {
        Tab remove = tabs.remove(0);
        p.setOnFinished(e2 -> tabs.add(1, remove));
        p.play();
    });
    

    这是异步调用返回的足够时间(不要过快地调用KeyPressed处理程序,因为您将删除选项卡的速度超过可以添加的选项卡)。您可以使用

    关闭删除动画
    tabPane.setStyle("-fx-close-tab-animation: NONE;");
    

    允许您减少暂停持续时间。在我的机器上15是安全的(在这里你也可以连续快速调用KeyPressed处理程序,因为延迟很短)。

    可能的修复

    tabHeaderArea上的某些同步。