4

3 つのパネルを含む JTabbedPane を持つ単純な JFrame があり、2 番目のパネルには JComponent が含まれているとします。「Tab 2」パネルがコンテナから削除されたときにJComponentに通知する方法はありますか? 私の問題は、JComponent が階層の奥深くにある可能性があることです。

明らかに、私はここで SWING ソリューションを探しています... :)

 ,'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''`.
 |                                                                |
 | ,----------Y.......................                            |
 | | Tab 1    | Tab 2     | Tab 3    |                            |
 | :..........:           :.....................................  |
 | |                                                           |  |
 | |                                                           |  |
 | |                                                           |  |
 | |               +--------------------+                      |  |
 | |               |Some JComponent here|                      |  |
 | |               +--------------------+                      |  |
 | |                                                           |  |
 | |                                                           |  |
 | |                                                           |  |
 | |                                                           |  |
 | |                                                           |  |
 | |                                                           |  |
 | |                                                           |  |
 | |                                                           |  |
 | |                                                           |  |
 | |                                                           |  |
 | `-----------------------------------------------------------'  |
 `-----------------------------------------------------------------

私は祖先の削除()でこれをやろうとしましたが、うまくいきません...私は明らかに何か間違ったことをしています...

PS。アスキーアートはJavaEで作られています。

4

3 に答える 3

4

私はComponentListenerこの仕事に使用されます (CardLayout非常に近く、 と比較して似ていJTabbedPaneます)、コード例には関連するすべてのリスナーが含まれています (免責事項 --> EDT のブロックはコード例としてのみ機能し、この形式でのみ機能することに注意してください)

Ancesor & HierarchyListener少し非同期です。適切なイベントをキャッチするのに問題があるかもしれませんAncestorListener

同様の問題に関する私の質問

import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.event.HierarchyEvent;
import java.awt.event.HierarchyListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.event.AncestorEvent;
import javax.swing.event.AncestorListener;

public class CardlayoutTest extends JFrame {

    private static final long serialVersionUID = 1L;
    public CardLayout card = new CardLayout();

    public CardlayoutTest() {
        JPanel pnlA = new JPanel(new BorderLayout());
        pnlA.add(new JButton("A"), BorderLayout.CENTER);
        JPanel pnlB = new JPanel(new BorderLayout());
        pnlB.add(new JButton("B"), BorderLayout.CENTER);
        JPanel pnlC = new JPanel(new BorderLayout());
        pnlC.add(new JButton("C"), BorderLayout.CENTER);

        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setLayout(card);
        add(pnlA, "A");
        add(pnlB, "B");
        add(pnlC, "C");

        pnlA.addAncestorListener(new EventHandler());
        pnlB.addAncestorListener(new EventHandler());
        pnlC.addAncestorListener(new EventHandler());

        pnlA.addHierarchyListener(new EventHandler());
        pnlB.addHierarchyListener(new EventHandler());
        pnlB.addHierarchyListener(new EventHandler());

        pnlA.addComponentListener(new EventHandler());
        pnlB.addComponentListener(new EventHandler());
        pnlB.addComponentListener(new EventHandler());
    }

    class EventHandler implements AncestorListener, ComponentListener, HierarchyListener {

        @Override
        public void ancestorAdded(AncestorEvent event) {
            System.out.println("CardlayoutTest.EventHandler.ancestorAdded()");
        }

        @Override
        public void ancestorMoved(AncestorEvent event) {
            System.out.println("CardlayoutTest.EventHandler.ancestorMoved()");
        }

        @Override
        public void ancestorRemoved(AncestorEvent event) {
            System.out.println("CardlayoutTest.EventHandler.ancestorRemoved()");
        }

        @Override
        public void hierarchyChanged(HierarchyEvent e) {
            System.out.println("Components Change: " + e.getChanged());
            if ((e.getChangeFlags() & HierarchyEvent.DISPLAYABILITY_CHANGED) != 0) {
                if (e.getComponent().isDisplayable()) {
                    System.out.println("Components DISPLAYABILITY_CHANGED : " + e.getChanged());
                } else {
                    System.out.println("Components DISPLAYABILITY_CHANGED : " + e.getChanged());
                }
            }
            if ((e.getChangeFlags() & HierarchyEvent.SHOWING_CHANGED) != 0) {
                if (e.getComponent().isDisplayable()) {
                    System.out.println("Components SHOWING_CHANGED : " + e.getChanged());
                } else {
                    System.out.println("Components SHOWING_CHANGED : " + e.getChanged());
                }
            }
        }

        public void componentHidden(ComponentEvent e) {
            System.out.println(e.getComponent().getClass().getName() + " --- Hidden");
        }

        public void componentMoved(ComponentEvent e) {
            System.out.println(e.getComponent().getClass().getName() + " --- Moved");
        }

        public void componentResized(ComponentEvent e) {
            System.out.println(e.getComponent().getClass().getName() + " --- Resized ");
        }

        public void componentShown(ComponentEvent e) {
            System.out.println(e.getComponent().getClass().getName() + " --- Shown");
        }
    }

    public static void main(String[] args) {
        CardlayoutTest t = new CardlayoutTest();
        t.setSize(500, 500);
        System.out.println("CardlayoutTest.main()------------------------ FIRST");
        t.card.show(t.getContentPane(), "A");
        t.setVisible(true);
        System.out.print("\n");
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
        }
        System.out.println("CardlayoutTest.main()------------------------ SECOND");
        t.card.show(t.getContentPane(), "B");
        System.out.print("\n");
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
        }
        System.out.println("CardlayoutTest.main()------------------------ THIRD");
        t.card.show(t.getContentPane(), "C");
        System.out.print("\n");
    }
}
于 2013-02-12T14:05:32.437 に答える
4

何かをする必要があるのがコンポーネント自体である場合は、add/removeNotify をオーバーライドすることもできます (super を呼び出すことを忘れないでください。

import java.awt.*;
import java.awt.event.*;
import java.util.Date;
import javax.swing.*;

public class LabelWithTimer extends JLabel {

    private final Timer timer;

    public LabelWithTimer() {
        timer = new Timer(1000, new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                setText(new Date().toString());
            }
        });
    }

    @Override
    public void addNotify() {
        super.addNotify();
        timer.start();
        System.out.println("Clock started");
    }

    @Override
    public void removeNotify() {
        System.out.println("Clock stopped");
        timer.stop();
        super.removeNotify();
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                final JPanel clock = new JPanel(new GridBagLayout());
                clock.add(new LabelWithTimer());

                final JTabbedPane tabs = new JTabbedPane();
                tabs.addTab("Empty", new JLabel());
                tabs.setPreferredSize(new Dimension(400, 300));

                JFrame frame = new JFrame("Test");
                frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
                frame.getContentPane().add(tabs);
                frame.getContentPane().add(new JButton(new AbstractAction("Add/remove clock") {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        if(tabs.getTabCount() == 2) {
                            tabs.removeTabAt(1);
                        }
                        else {
                            tabs.addTab("Clock", clock);
                            tabs.setSelectedIndex(1);
                        }

                    }
                }), BorderLayout.PAGE_END);
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }
}
于 2013-02-12T16:07:00.110 に答える
3

HierarchyListenerを使用する良い例を投稿してくれたmKorbelのおかげで、私は自分のニーズを満たしていると信じる解決策を思いつきました。この場合JLabel、通知が必要なコンポーネントとして使用します。

彼が私に多くの時間を節約したという理由だけで、私はmKorbelの答えを受け入れます。

コードは次のとおりです。

import java.awt.BorderLayout;
import java.awt.EventQueue;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.event.AncestorEvent;
import javax.swing.event.AncestorListener;
import javax.swing.JTabbedPane;
import javax.swing.JButton;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.event.HierarchyEvent;
import java.awt.event.HierarchyListener;

public class TestFrame extends JFrame {
    private static final long serialVersionUID = 8388031406846751884L;
    private JPanel contentPane;
    private JTabbedPane tabbedPane;
    private JLabel label; /// The component that needs to be notified when it should save its states.

    /**
     * Launch the application.
     */
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    TestFrame frame = new TestFrame();
                    frame.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    /**
     * Adds necessary listeners.
     * @param argLabel
     */
    private void install(JLabel argLabel) {
        // ::::: HierarchyListener ::::::::::::::::::::::::::::::::::::::::::::::::::::::::
        argLabel.addHierarchyListener(new HierarchyListener() {
            @Override
            public void hierarchyChanged(HierarchyEvent arg0) {
                if ((arg0.getChangeFlags() & HierarchyEvent.DISPLAYABILITY_CHANGED) != 0) {
                    if (!arg0.getComponent().isDisplayable()) {
                        // component is not displayable due to the panel being removed
                        doSomething();
                    }
                }
            } 
        });

        // ::::: AncestorListener :::::::::::::::::::::::::::::::::::::::::::::::::::::::::
        argLabel.addAncestorListener(new AncestorListener() {

            @Override
            public void ancestorAdded(AncestorEvent arg0) {
                // not interested in this one
            }

            @Override
            public void ancestorMoved(AncestorEvent arg0) {
                // not interested in this one
            }

            @Override
            public void ancestorRemoved(AncestorEvent arg0) {
                // ancestorRemoved() is useful when user navigates between tabs, and causes
                // component to become invisible.
                doSomething();
            } 
        });
    }

    public void doSomething() {
        System.out.println("Saving some state(s)...");
    }

    /**
     * Create the frame.
     */
    public TestFrame() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(100, 100, 693, 376);
        contentPane = new JPanel();
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
        contentPane.setLayout(new BorderLayout(0, 0));
        setContentPane(contentPane);

        tabbedPane = new JTabbedPane(JTabbedPane.TOP);
        // first panel
        tabbedPane.add(new JPanel()); 
        // second panel
        JPanel panelWithComponents = new JPanel();
        JPanel childPanel = new JPanel();
        label = new JLabel("Test label");
        install(label);
        childPanel.add(label);
        panelWithComponents.add(childPanel);
        tabbedPane.add(childPanel);
        // third panel
        tabbedPane.add(new JPanel());

        contentPane.add(tabbedPane, BorderLayout.CENTER);

        JButton btnRemove = new JButton("Remove second");
        btnRemove.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
                tabbedPane.remove(1);
            }
        });
        contentPane.add(btnRemove, BorderLayout.SOUTH);
    } // main() method

} // TestFrame class
于 2013-02-12T15:17:53.833 に答える