Как добавить кнопку закрытия на вкладку JTabbedPane?

Я работаю с JTabbedPane, мне нужно добавить кнопку закрытия на вкладках, чтобы закрыть текущую.

Я искал, и, насколько я понимаю, я должен расширить JPanel и добавить кнопку закрытия, как они говорят здесь Но есть ли способ добавить кнопки закрытия, расширяющие JTabbedPane, или есть более простой способ сделать это?

Заранее спасибо, я очень ценю ваше время и вашу помощь.


person Hermandroid    schedule 19.07.2012    source источник
comment
Это может быть полезно — stackoverflow. ком/вопросы/10620630/   -  person user1329572    schedule 19.07.2012
comment
спасибо пойду проверю   -  person Hermandroid    schedule 20.07.2012


Ответы (6)


По сути, вам нужно будет предоставить «рендерер» для вкладки. Взгляните на JTabbedPane.setTabComponentAt(...) для получения дополнительной информации.

Основная идея заключается в том, чтобы поставить компонент, который будет выложен на вкладке.

Обычно я создаю JPanel, на который я добавляю JLabel (для заголовка) и, в зависимости от того, что я хочу отобразить, какой-то элемент управления, который действует как действие закрытия.

tabPane.addTab(title, tabBody);
int index = tabPane.indexOfTab(title);
JPanel pnlTab = new JPanel(new GridBagLayout());
pnlTab.setOpaque(false);
JLabel lblTitle = new JLabel(title);
JButton btnClose = new JButton("x");

GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.weightx = 1;

pnlTab.add(lblTitle, gbc);

gbc.gridx++;
gbc.weightx = 0;
pnlTab.add(btnClose, gbc);

tabPane.setTabComponentAt(index, pnlTab);

btnClose.addActionListener(myCloseActionHandler);

Теперь в другом месте я устанавливаю обработчик действий...

public class MyCloseActionHandler implements ActionListener {

    public void actionPerformed(ActionEvent evt) {

        Component selected = tabPane.getSelectedComponent();
        if (selected != null) {

            tabPane.remove(selected);
            // It would probably be worthwhile getting the source
            // casting it back to a JButton and removing
            // the action handler reference ;)

        }

    }

}

Теперь вы так же легко можете использовать любой компонент, который вам нравится, и прикрепить к нему прослушиватель мыши и отслеживать щелчки мыши...

Обновлено

В приведенном выше примере будет удалена только активная в данный момент вкладка, есть несколько способов исправить это.

Лучше всего, вероятно, предоставить какие-то средства для действия, чтобы найти вкладку, с которой оно связано...

public class MyCloseActionHandler implements ActionListener {

    private String tabName;

    public MyCloseActionHandler(String tabName) {
        this.tabName = tabName;
    }

    public String getTabName() {
        return tabName;
    }

    public void actionPerformed(ActionEvent evt) {

        int index = tabPane.indexOfTab(getTabName());
        if (index >= 0) {

            tabPane.removeTabAt(index);
            // It would probably be worthwhile getting the source
            // casting it back to a JButton and removing
            // the action handler reference ;)

        }

    }

}   

Это использует имя вкладки (как используется с JTabbedPane#addTab), чтобы найти, а затем удалить вкладку и связанный с ней компонент...

person MadProgrammer    schedule 19.07.2012
comment
Спасибо!!! это здорово выглядит. Я собираюсь проверить это во второй половине дня. Я очень ценю вашу помощь - person Hermandroid; 20.07.2012
comment
Это попытка. Если вы читаете код, ActionListener использует выбранную вкладку. Вы связываете компонент вкладки с прослушивателем действий, находите индекс и вместо этого удаляете его. - person MadProgrammer; 18.05.2013
comment
Обновлен с дополнительным примером - person MadProgrammer; 18.05.2013
comment
См. также отличный (1) пример (1) с гораздо более высоким коэффициентом скриншоты летающих пони (с оружием). :) - person Andrew Thompson; 15.07.2013

Я нашел пример вкладки (с сайта Java), который, по-видимому, делает это, по крайней мере, у них. (Хотя я думал, когда я пробовал это в прошлом, что он также закрывал текущую выбранную вкладку, хотя он работает правильно, когда вы запускаете их пример, хотя я думаю, что когда я обновил его для работы в блокноте Java с вкладками, он закрывался текущая выбранная вкладка, хотя, возможно, я сделал это неправильно.

http://docs.oracle.com/javase/tutorial/displayCode.html?code=http://docs.oracle.com/javase/tutorial/uiswing/examples/components/TabComponentsDemoProject/src/components/ButtonTabComponent.java

Да, моя вещь работает сейчас! Это БУДЕТ работать для фактической вкладки, а не для выбранной в данный момент вкладки!

person MongooseLover    schedule 26.08.2013
comment
Тем не менее, вы должны знать, что таким образом вы лишаетесь возможности устанавливать значки вкладок. (Если вы не хотите возиться с нижними уровнями, смотреть исходный код и делать paintComponent() и все такое забавное, я не вижу способа обойти эту проблему.) - person MongooseLover; 29.11.2013

Надеюсь, вы получили ответ на свой вопрос. Хочу дать очень полезную для меня ссылку.

JTabbedPane с кнопкой закрытия

Вот тоже код.

public static void createAndShowGUI()
{
    JFrame frame = new JFrame("Tabs");
    frame.setMinimumSize(new Dimension(500, 200));
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    JTabbedPane tabbedPane = new JTabbedPane();

    JPanel panel = new JPanel();
    panel.setOpaque(false);
    tabbedPane.add(panel);
    tabbedPane.setTabComponentAt(tabbedPane.indexOfComponent(panel), getTitlePanel(tabbedPane, panel, "Tab1"));

    JPanel panel1 = new JPanel();
    panel1.setOpaque(false);
    tabbedPane.add(panel1);
    tabbedPane.setTabComponentAt(tabbedPane.indexOfComponent(panel1), getTitlePanel(tabbedPane, panel1, "Tab2"));

    JPanel panel2 = new JPanel();
    panel2.setOpaque(false);
    tabbedPane.add(panel2);
    tabbedPane.setTabComponentAt(tabbedPane.indexOfComponent(panel2), getTitlePanel(tabbedPane, panel2, "Tab3"));

    JPanel panel3 = new JPanel();
    panel3.setOpaque(false);
    tabbedPane.add(panel3);
    tabbedPane.setTabComponentAt(tabbedPane.indexOfComponent(panel3), getTitlePanel(tabbedPane, panel3, "Tab4"));

    frame.add(tabbedPane);

    // Display the window.
    frame.pack();
    frame.setVisible(true);
}
person Sardar Faisal    schedule 16.02.2014

Я внес некоторые изменения в код oracle.

http://docs.oracle.com/javase/tutorial/displayCode.html?code=http://docs.oracle.com/javase/tutorial/uiswing/examples/components/TabComponentsDemoProject/src/components/ButtonTabComponent.java

Предоставление возможности добавить значок на вкладку, а также кнопку закрытия вкладки. Надеюсь, это поможет.

public static void addTag(JTabbedPane tab, String title, Icon icon, int index){
     MouseListener close = new MouseAdapter() {

        @Override
        public void mouseClicked(MouseEvent e) {
            //your code to remove component
            //I use this way , because I use other methods of control than normal: tab.remove(int index);
        }

    };
    final ButtonClose buttonClose = new ButtonClose (title, icon, close );

    tab.setTabComponentAt(index, buttonClose);
    tab.validate();
    tab.setSelectedIndex(index);

}

открытый класс ButtonClose расширяет JPanel {

public ButtonClose(final String title, Icon icon, MouseListener e) {
    JLabel ic = new JLabel(icon);
    ic.setSize(icone.getIconWidth(), icone.getIconHeight());

    JLabel text= new JLabel(title);
    text.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 5));

    ButtonTab button = new ButtonTab();
    button.addMouseListener(e);
    button.setBorder(BorderFactory.createEmptyBorder(2, 0, 0, 0));

    JPanel p = new JPanel();
    p.setSize(getWidth() - icone.getIconWidth(), 15);
    p.add(text);
    p.add(button);

    add(ic);
    add(p);
}

private class ButtonTab extends JButton {

    public ButtonTab() {
        int size = 13;
        setPreferredSize(new Dimension(size, size));
        setToolTipText("Close");

        setUI(new BasicButtonUI());

        setFocusable(false);
        setBorderPainted(false);

        addMouseListener(listener);
        setRolloverEnabled(true);
    }

    @Override
    public void updateUI() {
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g.create();

        if (getModel().isPressed()) {
            g2.translate(1, 1);
        }
        g2.setStroke(new BasicStroke(2));
        g2.setColor(new Color(126, 118, 91));

        if (getModel().isRollover()) {
            g2.setColor(Color.WHITE);
        }

        int delta = 3;
        g2.drawLine(delta, delta, getWidth() - delta - 1, getHeight() - delta - 1);
        g2.drawLine(getWidth() - delta - 1, delta, delta, getHeight() - delta - 1);
        g2.dispose();
    }
}

private final MouseListener listener = new MouseAdapter() {
    @Override
    public void mouseEntered(MouseEvent e) {
        Component component = e.getComponent();
        if (component instanceof AbstractButton) {
            AbstractButton button = (AbstractButton) component;
            button.setContentAreaFilled(true);
            button.setBackground(new Color(215, 65, 35));
        }
    }

    @Override
    public void mouseExited(MouseEvent e) {
        Component component = e.getComponent();
        if (component instanceof AbstractButton) {
            AbstractButton button = (AbstractButton) component;
            button.setContentAreaFilled(false); //transparent
        }
    }
};

}

person Fábio Bertotti    schedule 06.11.2014

Ознакомьтесь с Peter-Swing здесь. В нем есть класс JClosableTabbedPane, а также многие другие.

Когда вы загрузите файл jar, вы сможете запустить его и получить примеры всех классов.

person Sheikh    schedule 19.11.2014

Вы можете иметь JLabel с именем «x» и использовать mouseListener

 private final JLabel l = new JLabel(); // this is the label for tabbedPane
 private final JLabel b = new JLabel("x");//Close Button
 if (closeable)
        {
            b.setToolTipText("Click to close");

            b.setOpaque(false);
            b.setBackground(Color.gray);

            b.addMouseListener(new MouseAdapter()
            {
                @Override
                public void mouseExited(MouseEvent e)
                {
                    b.setBorder(bordere);
                    b.setOpaque(false);
                }

                @Override
                public void mouseEntered(MouseEvent e)
                {
                    b.setBorder(borderl);
                }

                @Override
                public void mouseReleased(MouseEvent e)
                {
                    b.setOpaque(false);
                    b.repaint();

                    if (b.contains(e.getPoint()))
                    {
                        b.setBorder(borderl);

                        if (confirmTabClosing())
                        {
                            tab.remove(tabIndex());
                            if(tab.getTabCount() == 0)
                                spacialTabComponent.maximizeOrRestore.doClick();
                        }
                    }
                    else
                        b.setBorder(bordere);

                }

                @Override
                public void mousePressed(MouseEvent e)
                {
                    b.setOpaque(true);
                    b.repaint();
                }
            });

            b.setBorder(bordere);
            add(b, getLeftAlignedBothFilledGBC(1, 0, new Insets(0, 0, 0, 0), 0, 0));
        }



    }
person Diya    schedule 02.12.2014