Как да добавите бутон за затваряне към раздел JTabbedPane?

Работя с JTabbedPane, трябва да добавя бутон за затваряне в разделите, за да затворя текущия.

Търсих и доколкото разбирам, трябва да се разширя от JPanel и да добавя бутона за затваряне, както се казва тук Но има ли начин да добавите бутоните за затваряне, разширяващи JTabbedPane, или има по-лесен начин да го направите?

Благодаря предварително, наистина оценявам времето и помощта ви.


person Hermandroid    schedule 19.07.2012    source източник
comment
Това може да е полезно - stackoverflow. com/questions/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 използва избрания раздел. Свързвате компонента tab със слушателя на действие, намирате индекса и го премахвате вместо това - 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