2

我有一个具有以下节点布局的 JavaFX 应用程序:

  • 拆分窗格
    • 文本区域
    • 拆分窗格
      • 选项卡窗格
      • 选项卡窗格

在此处输入图像描述

示例代码:

SplitPane topBottomSplitPane = new SplitPane();

TextArea displayTextArea = new TextArea();
SplitPane leftRightSplitPane = new SplitPane();

topBottomSplitPane.getItems().addAll(displayTextArea, leftRightSplitPane);

TabPane leftTabPane = new TabPane();
TabPane rightTabPane = new TabPane();

leftRightSplitPane.getItems().addAll(leftTabPane, rightTabPane);

TextArea,displayTextArea,是一个不可编辑的文本区域,它显示一些文本数据,具体取决于两个 TabPanes、leftTabPane 和 rightTabPane 内打开的 Tab 对象中存在的数据。TabPane 的 SelectionModel 是单数的,因此每个 TabPane 一次只能选择一个选项卡。

我的限制之一是只有一个打开的 Tab 对象数据应该影响 displayTextArea 的文本。当只有一个 TabPane 对象时,这很容易实现,方法是设置 OnSelectionChanged EventHandler 并使用 isSelected() 来确定选择的更改是进入还是退出选择。并且选定的选项卡将是影响 displayTextArea 的选项卡。

当有两个 TabPanes 时,我希望内容节点当前具有焦点的选项卡,例如 TextField 或用户正在输入将影响 displayTextArea 文本的数据的表单。从用户的角度来看,他们将单击 TabPanes 中打开的选项卡,而他们最后一次单击的选项卡将影响 displayTextArea。但这就是我撞墙的地方。

尝试和失败的方法:

  1. 设置某种侦听器以通知焦点从一个选项卡的内容节点到另一个选项卡的内容节点,无论它们在哪个 TabPane 中,然后相应地更新 displayTextArea。- 没有 AddFocusListener 方法,我不确定如何使用可用的面向焦点的方法和功能来实现此行为。

  2. 强制在多个 TabPanes 之间的任一时间只选择 1 个 Tab,并坚持使用上述 OnSelectionChanged EventHandler 方法。- 我不知道从哪里开始,也找不到任何东西。

在这个问题中,有一个主题是在选项卡的内容节点中将焦点更改为 TextField 对象,但我无法从该帖子中获取任何对我的目的有用的东西。

我在这里迷路了,不知道如何实现此显示的必要功能。

4

3 回答 3

2

我想出了一个合理且相当简单的解决方案:

问题用例:(请参阅有问题的图片以获取用例参考)

  1. 目前 Tab1(位于左侧 TabPane 中)正在影响显示。
  2. 用户单击 Tab4(位于右侧 TabPane 中)。

上述用例的问题在于,Tab1 和 Tab4 都是当前为其各自的 TabPanes 选择的选项卡。因此,没有选项卡的 isSelected 布尔值发生变化,并且它们的 onSelectionChanged EventHandler 不会被触发。

解决方案:

  1. 设置对 Tab 的全局引用,该引用指向影响 TextArea 显示的当前 Tab。
  2. 对于每个 Tab,在两个 TabPanes 中,设置一个 onSelectionChanged EventHandler,它首先检查此选项卡是否成为选定的选项卡或只是丢失了选择。
    1. 如果它刚刚成为选定的选项卡
      1. 设置全局引用 Tab 指向自身
      2. 根据其内容更新 TextArea 显示
    2. 如果不是选中的选项卡
      1. 没做什么
  3. 在两个 TabPanes 上设置 OnMouseClicked EventHandler
    1. 如果全局引用 Tab 不包含在此 TabPane 中
      1. 设置全局引用 Tab 指向这个 TabPane 的当前选中的 Tab
      2. 根据此 TabPane 当前选择的 Tab 的内容更新 TextArea Display
    2. 如果全局引用 Tab IS 包含在此 TabPane 中,则什么也不做。选项卡上的 onSelectionChanged EventHandler 本身已经正确更新了 TextArea 显示

如果有人需要更多解释,或者会从该算法的编码示例实现中受益,只需发表评论要求,我会很快为您提供一个。

于 2013-06-20T00:27:22.000 回答
0

我使用 FXML onSelectionChange 方法实现了一个简单的解决方案,如下所示。

首先,我会考虑整个窗格只有一个控制器,因此无论您在何处使用或使用多少个选项卡都没有关系。

对于每个选项卡,在 FXML(可以编码)上,我添加了一个 onSelectionChanged 侦听器方法。问题是,在任何选项卡选择之后,JavaFX 都会通知两个涉及的选项卡(按此顺序):新选择的选项卡和先前选择的选项卡。所以,我只是放了一个布尔变量来标记这是第一次还是第二次调用。

注意:请注意,如果此通知策略在未来发生变化,此解决方案可能会有风险。

我的控制器代码的一部分:

private boolean tabSelection = false;

@FXML void reportsTabSelected(Event e) {
    if (checkTab()) {
        System.out.println("Reports Tab is Now Selected");
    }
}
@FXML void configTabSelected(Event e) {
    if (checkTab()) {
        System.out.println("Configs Tab is Now Selected");
    }
}

private boolean checkTab() {
    tabSelection = !tabSelection;
    return tabSelection;
}

部分选项卡 FXML:

<Tab text="REPORTS" fx:id="reportsTab" onSelectionChanged="#reportsTabSelected">
</Tab>
<Tab text="CONFIGURATIONS" fx:id="configurationsTab" onSelectionChanged="#configTabSelected">
</Tab>
于 2015-02-17T09:00:16.363 回答
0

由于displayTextArea一次只能显示与四个选项卡之一相关的内容,因此您不需要尝试将两组选项卡链接在一起。相反,每个选项卡窗格都可以对选择更改有自己的响应。它们之间唯一的共同点是所有选择更改都将调用填充displayTextArea的相同方法。出于本示例的目的,让我们调用该方法setDisplayTextAreaContent,还假设通过将该方法传递给最近选择的选项卡,它将知道如何填充displayTextArea。在做出这些假设以及我正确理解您的问题的假设之后,解决方案可能看起来像这样......

    TabPane tabPane1 = new TabPane();
    final Tab tab1 = new Tab();
    final Tab tab2 = new Tab();
    tabPane1.getTabs().addAll(tab1, tab2);
    tabPane1.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<Tab>()
    {
        @Override
        public void changed(ObservableValue<? extends Tab> arg0, Tab arg1, Tab mostRecentlySelectedTab)
        {
            if (mostRecentlySelectedTab.equals(tab1))
            {
                setDisplayTextAreaContent(tab1);
            }
            if (mostRecentlySelectedTab.equals(tab2))
            {   
                setDisplayTextAreaContent(tab2);
            }
        }
    });

    TabPane tabPane2 = new TabPane();
    final Tab tab3 = new Tab();
    final Tab tab4 = new Tab();
    tabPane2.getTabs().addAll(tab1, tab2);
    tabPane2.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<Tab>()
    {
        @Override
        public void changed(ObservableValue<? extends Tab> arg0, Tab arg1, Tab mostRecentlySelectedTab)
        {
            if (mostRecentlySelectedTab.equals(tab3))
            {
                setDisplayTextAreaContent(tab3);
            }
            if (mostRecentlySelectedTab.equals(tab4))
            {   
                setDisplayTextAreaContent(tab4);
            }
        }
    });

您可以改为向 TabPanes 的selectedIndexProperty添加一个侦听器,如果这对您更有效(假设您知道哪些选项卡位于它们各自的 TabPanes 内的哪个索引处)。我希望这个答案可以帮助你。如果您有任何问题,请告诉我,如果可以的话,我很乐意回答。

于 2013-06-06T20:48:23.653 回答