概述:
我必须开发一个JTabbedPane
,它应该有一个默认选项卡,只有在没有显示其他选项卡时才会显示(我使用ContainerListener
实现)。
此外,它应该为每个添加的标签创建一个自定义标题(我实现了覆盖addTab
)。
遵循可以按原样使用的MCVE:
public class MyCustomTabbedPane extends JTabbedPane {
private final JPanel defaultTab = new JPanel();
public MyCustomTabbedPane() {
super();
JButton exampleButton = new JButton("Click me");
exampleButton.addActionListener((e) -> addTab("New page", null, new JPanel()));
defaultTab.add(exampleButton);
addTab("Default", null, defaultTab);
addContainerListener(new ContainerListener() {
@Override
public void componentRemoved(ContainerEvent e) {
if (getTabCount() == 0) {
addTab("Default", null, defaultTab);
}
}
@Override
public void componentAdded(ContainerEvent e) {
if (getTabCount() > 1) {
remove(defaultTab);
}
}
});
}
@Override
public void addTab(String title, Icon icon, Component component) {
int index = getTabCount();
// Add new tab at the back with default header
super.addTab(title, icon, component);
// Create custom header based on default header
Component header = createHeader(title, icon, getTabComponentAt(index));
// Set custom header for added tab
setTabComponentAt(index, header);
// Select the added tab
setSelectedIndex(index);
}
private Component createHeader(String title, Icon icon, Component header) {
if(header == null) {
header = new JLabel(title, icon, SwingConstants.LEFT);
}
JPanel panel = new JPanel();
panel.add(new JLabel("Just an example header modification - "));
panel.add(header);
return panel;
}
}
问题:
问题发生在super.addTab(title, icon, component);
覆盖范围内addTab
,因为此时会触发componentAdded
事件。由于此事件,将删除默认页面(因此,选项卡的数量会更改)。因此,index
中addTab
的值不再正确,导致java.lang.IndexOutOfBoundsException: Index: 1, Size: 1
。
问题:
我可以告诉JTabbedPane
延迟super.addTab(title, icon, component)
和setTabComponentAt(index, header)
之间的事件吗?如果这不可能,是否有另一种方法如何添加带有自定义标题的新标签,而不首先添加带有默认标题的标签?
答案 0 :(得分:0)
嗯,我想最简单的方法是在super.addTab()
行之后添加一行
index = index == getTabCount() ? 0 : index
或
index = index == getTabCount() ? index - 1 : index
或
if (index == getTabCount()) { index-- }
答案 1 :(得分:0)
通过使用以下代码,我能够摆脱index
中addTab()
的需求(请参阅setSelectedComponent()
替换setSelectedIndex()
和indexOfComponent(component)
替换在index
上使用。
这样,我绕过了对无效索引的访问。
public class MyCustomTabbedPane extends JTabbedPane {
private final JPanel defaultTab = new JPanel();
public MyCustomTabbedPane() {
super();
JButton exampleButton = new JButton("Click me");
exampleButton.addActionListener((e) -> addTab("New page", null, new JPanel()));
defaultTab.add(exampleButton);
addTab("Default", null, defaultTab);
addContainerListener(new ContainerListener() {
@Override
public void componentRemoved(ContainerEvent e) {
if (getTabCount() == 0) {
addTab("Default", null, defaultTab);
}
}
@Override
public void componentAdded(ContainerEvent e) {
if (getTabCount() > 1) {
remove(defaultTab);
}
}
});
}
@Override
public void addTab(String title, Icon icon, Component component) {
// Add new tab at the back with default header
super.addTab(title, icon, component);
// Create custom header based on default header
Component header = createHeader(title, icon, getTabComponentAt(indexOfComponent(component)));
// Set header for previously added tab
setTabComponentAt(indexOfComponent(component), header);
// Select the added tab
setSelectedComponent(component);
}
private Component createHeader(String title, Icon icon, Component header) {
if(header == null) {
header = new JLabel(title, icon, SwingConstants.LEFT);
}
JPanel panel = new JPanel();
panel.add(new JLabel("Just an example header modification - "));
panel.add(header);
return panel;
}
}