JavaFX选项卡窗格选项卡不带';t更新位置

JavaFX选项卡窗格选项卡不带';t更新位置,java,javafx,tabs,javafx-2,tabpanel,Java,Javafx,Tabs,Javafx 2,Tabpanel,我注意到,在选项卡窗格中添加和删除选项卡时,它无法匹配基本列表中选项卡顺序的位置。只有当至少一个选项卡由于父选项卡的宽度而完全隐藏时,才会发生这种情况。下面是一些复制问题的代码: public class TabPaneTester extends Application { @Override public void start(Stage primaryStage) throws Exception { Scene scene = sizeScene();

我注意到,在
选项卡窗格
中添加和删除选项卡时,它无法匹配基本列表中选项卡顺序的位置。只有当至少一个选项卡由于父选项卡的宽度而完全隐藏时,才会发生这种情况。下面是一些复制问题的代码:

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();
    }

}
public类TabPaneTester扩展应用程序{
@凌驾
public void start(Stage primaryStage)引发异常{
Scene-Scene=sizeScene();
初生阶段:最低高度(200);
初生阶段,坐骨宽度(475);
初级阶段。场景(场景);
primaryStage.show();
}
私人场景sizeScene(){
TabPane TabPane=新建TabPane();
tabPane.setTabMinWidth(200);
tabPane.getTabs().addAll(newTabs(3));
场景=新场景(选项卡窗格);
按scene.setOnKeyPressed(e->tabPane.getTabs().add(1,tabPane.getTabs().remove(0));
返回场景;
}
私有静态选项卡[]newTabs(int numTabs){
Tab[]tabs=新选项卡[numTabs];
对于(int i=0;i
当您按下一个键时,它会删除第一个选项卡(在索引0处)并将其放回索引1,从而有效地交换前两个选项卡。但是,当运行时,选项卡实际上不会在视觉上交换(即使选项卡切换菜单确实切换了它们的位置)

如果将屏幕宽度更改为包含第三个隐藏选项卡的一个像素(将475替换为500),它将按预期工作。关于如何修复这个问题,有什么线索吗?

这确实是一个bug,我在公开的JIRA中找不到它的报道,现在它被报道在

如果您想亲自查看,我所有的分析都基于
TabPaneSkin
中的代码

总结 当您删除然后添加选项卡“太快”时,问题就会出现。移除选项卡时,将在移除过程中进行异步调用。如果您进行了另一项更改,例如在异步调用完成之前添加了一个选项卡(或者至少“足够完成”),那么更改过程会看到窗格处于无效状态

细节 删除选项卡将调用
removeTabs
,如下所示:

  • 调用各种内部移除方法
  • 然后检查是否应设置关闭动画。
    • 如果是(
      增长
      ),
    • 动画将对
      requestLayout
      方法的调用排队,该方法本身是异步调用的
    • 动画开始(异步)并返回方法
    • 如果不是(
      NONE
      ),
    • 立即调用
      requestLayout
      ,方法返回
  • 窗格处于无效状态的时间是从调用返回到
    requestLayout
    返回(在另一个线程上)的时间。此持续时间等于
    requestLayout
    的持续时间加上动画的持续时间(如果有),即
    animation\u 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();
    });
    
    这允许您减少暂停持续时间。在我的机器上,15是安全的(这里你也可以连续快速调用
    按键
    处理程序,因为延迟很短)

    可能的解决办法
    tabHeaderArea
    上的一些同步

    我想你发现了一只虫子。如果在
    .add(2,yourTab)
    中使用2,您将看到新的
    选项卡的位置比它应该处于的位置少一个。您能解释一下这是如何导致该行为的吗?我看不出所选选项卡如何影响它们的位置,因为无论哪种方式,都应该删除第一个选项卡并更新列表,导致选项卡2显示(并选中)在前面,然后选项卡1放在后面。同样,如果宽度不重要,它如何改变行为?编辑:哎呀,虫子……一定是虫子。如果在再次添加选项卡后打印该选项卡的实际位置,它将显示与实际可视位置不同的位置。现在如果调用
    tabPane.autosize()在关键事件结束时,它将修复位置。似乎在fx9@kleopatra
    TabPaneSkin
    是否更改了其异步行为?
    tabPane.setStyle("-fx-close-tab-animation: NONE;");