如果在没有足够空间显示所有选项卡时尝试对选项卡进行排序,则JavaFX TabPane会有一种非常奇怪的行为。
更确切地说,选项卡选择按钮(选项卡窗格标题右侧带有向下箭头的圆形按钮)应显示包含所有选项卡的下拉列表,不显示任何内容
我创建了一个小测试来重现问题。只需单击几次(直到所有选项卡都没有足够的空间)“添加新选项卡&排序”(或“添加新选项卡”,然后“排序选项卡”几次),然后单击选项卡选项右上角的按钮......只是为了看它根本没有显示任何内容!
请注意,调整窗口大小以使所有选项卡都适合,然后将其调整大小以便再次显示选项卡选择按钮,从而解决问题。
这是重现的代码。我正在使用 jdk1.8.0_92 。看起来像JDK错误?
public class TabPaneTest extends Application {
public static void main(String[] args) {
TabPaneTest.launch();
}
int i = 1;
@Override
public void start(Stage primaryStage) throws Exception {
TabPane tabPane = new TabPane();
tabPane.getTabs().add(new Tab("My beautiful tab " + i, new TextArea("pane " + (i++))));
Button add = new Button("Add new tab");
add.setOnAction(event -> {
tabPane.getTabs().add(new Tab("My beautiful tab " + i, new TextArea("pane " + (i++))));
});
Button addSort = new Button("Add new tab & sort");
addSort.setOnAction(event -> {
tabPane.getTabs().add(new Tab("My beautiful tab " + i, new TextArea("pane " + (i++))));
tabPane.getTabs().sort((o1, o2) -> o2.getText().compareTo(o1.getText()));
});
Button sort = new Button("Sort tabs");
sort.setOnAction(event -> {
tabPane.getTabs().sort((o1, o2) -> o2.getText().compareTo(o1.getText()));
});
VBox vbox = new VBox(tabPane, new HBox(add, addSort, sort));
primaryStage.setScene(new Scene(vbox));
primaryStage.setWidth(400);
primaryStage.setHeight(300);
primaryStage.show();
}
}
答案 0 :(得分:3)
ListChangeListener
列表TabPaneSkin
中有一个Tab
,但不知道如上所述,它不会对列表进行排序。
作为一种解决方法,您可以将标签放在新列表中,并在排序后将其应用于TabPane
:
List<Tab> tabs = new ArrayList(tabPane.getTabs());
tabs.sort((o1, o2) -> o2.getText().compareTo(o1.getText()));
tabPane.getTabs().clear();
tabPane.getTabs().setAll(tabs);
答案 1 :(得分:3)
我想我在TabPaneSkin
课程中发现了问题&#39;方法removeTabs
:它会从tabHeaderArea.controlButtons.popup
:
// remove the menu item from the popup menu
ContextMenu popupMenu = tabHeaderArea.controlButtons.popup;
TabMenuItem tabItem = null;
if (popupMenu != null) {
for (MenuItem item : popupMenu.getItems()) {
tabItem = (TabMenuItem) item;
if (tab == tabItem.getTab()) {
break;
}
tabItem = null;
}
}
if (tabItem != null) {
tabItem.dispose();
popupMenu.getItems().remove(tabItem);
}
// end of removing menu item
这是一个问题,因为:
addTabs
没有相反的方法(即,不会将项目添加到弹出菜单中,并且 tabHeaderArea.controlButtons.popup
通过订阅tabPane.getTabs()
中的更改来自行管理其条目:
tabPane.getTabs().addListener((ListChangeListener<Tab>) c -> setupPopupMenu());
因此,他们都会从弹出菜单中删除这些项目,但由于在setupPopupMenu
之前调用removeTabs
,因此在使用addTabs
重新添加标签时,不会重新添加条目
我从removeTabs
方法删除了上述行,它运行正常。
将向JDK提交错误...
更新:
在http://Bugs.java.com(审核ID JI-9038050)提交了一个错误报告,但没有希望它会被修复(我在2015年9月提交的错误报告仍然是#34;等待&#34;)
与此同时,丑陋的解决方法(感谢@jns)是删除所有选项卡,对它们进行排序,然后再添加:
List<Tab> tabs = Lists.newArrayList(tabPane.getTabs());
tabs.sort((o1, o2) -> o2.getText().compareTo(o1.getText()));
tabPane.getTabs().clear();
tabPane.getTabs().setAll(tabs);
这很难看,因为你实际上可以看到标签消失然后再回来。
更新2:
更好的解决方法(再次感谢@jns)是在插入之前确定新选项卡的正确位置:
Comparator<Tab> comparator = (o1, o2) -> o2.getText().compareTo(o1.getText());
Button addSort = new Button("Add new tab, sorted");
addSort.setOnAction(event -> {
Tab newTab = new Tab("My beautiful tab " + i, new TextArea("pane " + (i++)));
// THIS IS WRONG! See UPDATE 3 below:
// int pos = Math.max(0, Collections.binarySearch(tabPane.getTabs(), newTab, comparator));
tabPane.getTabs().add(pos, newTab);
});
只有在每次插入新标签时排序顺序不变时,这才有效。如果您需要使用其他排序顺序对现有选项卡进行排序,则仍需要删除所有选项卡,排序,然后重新添加(请参阅解决方法1)。
更新3:
事实证明,Java binarySearch
只搜索精确匹配,而不是返回下限,因为我(经验丰富的C ++开发人员;)会期望......所以你需要设置以下的暴行来找到插入点:
<...>
int pos = 0;
while(pos < tabPane.getTabs().size() && tabPane.getTabs().get(pos).getText().compareTo(newTab.getText()) < 0) {
pos++;
}
tabPane.getTabs().add(pos, newTab);
<...>