JavaFX TabPane 选项卡不更新位置

标签 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

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

最佳答案

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

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

总结

当您“过快地”删除然后添加选项卡时,就会出现问题。删除选项卡后,将在删除过程中进行异步调用。如果您进行其他更改,例如在异步调用完成(或至少“完成足够”)之前添加选项卡,则更改过程会看到 Pane 处于无效状态。

详情

删除标签调用 removeTabs,概述如下:

  1. 调用了各种内部删除方法。
  2. 然后它检查关闭是否应该是动画的。
    • 如果是(GROW),
      1. 动画将对 requestLayout 方法的调用排队,该方法本身是异步调用的,
      2. 动画开始(异步),方法返回。
    • 如果不是(NONE),
      1. requestLayout 被立即调用,方法返回。

Pane 处于无效状态的时间是从调用返回到 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 上的一些同步。

关于JavaFX TabPane 选项卡不更新位置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47616221/

相关文章:

java - 如何知道方法是 N 还是 N^2

java - 使用java for chrome为网络浏览器开发插件

java - 如何将按钮的BackgroundTintList设置为默认值?

JavaFX Canvas 高效动画

javascript - Datepicker打开有些问题

facebook - 我们没有 SSL 站点,也将无法获得。我该如何解决这个问题?

android - fragment 可以作为 viewpager 而不是 Activity 的宿主吗?

java - 什么都不做的抽象方法实现

JavaFX Gradle Jlink-插件 : jpackageImage fails because of "[1.0-SNAPSHOT] contains invalid component [0-SNAPSHOT]"

java - 使用 JavaFX 将图像拖到窗口外