在JTabbedPane中设置自定义标头组件(TabComponent)的正确方法

时间:2016-04-05 12:47:06

标签: java jtabbedpane

概述:

我必须开发一个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事件。由于此事件,将删除默认页面(因此,选项卡的数量会更改)。因此,indexaddTab的值不再正确,导致java.lang.IndexOutOfBoundsException: Index: 1, Size: 1

问题:

我可以告诉JTabbedPane延迟super.addTab(title, icon, component)setTabComponentAt(index, header)之间的事件吗?如果这不可能,是否有另一种方法如何添加带有自定义标题的新标签,而不首先添加带有默认标题的标签?

2 个答案:

答案 0 :(得分:0)

嗯,我想最简单的方法是在super.addTab()行之后添加一行 index = index == getTabCount() ? 0 : index
index = index == getTabCount() ? index - 1 : index
if (index == getTabCount()) { index-- }

答案 1 :(得分:0)

通过使用以下代码,我能够摆脱indexaddTab()的需求(请参阅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;
    }
}