4

次のコードを使用して、コンポーネントが追加/削除されたときにイベントリスナーを登録/登録解除できるようにしています。

addAncestorListener(new AncestorListener() {
        @Override public void ancestorRemoved(AncestorEvent event) {
            log.info("========= Remove listeners by " + ContentViewingComponent.this);
            ...
        }
        @Override public void ancestorMoved(AncestorEvent event) {}
        @Override public void ancestorAdded(AncestorEvent event) {
            log.info("========= Add listeners by " + ContentViewingComponent.this);
            ...
        }
    });

私の意図は、両方のイベント(追加と削除)が基本的にほとんどの状況で1回発生することでした。つまり、コンポーネントが作成および追加されたときと、コンポーネントが削除および忘れられたときです。

JTabbedPaneただし、このコンポーネントが含まれている(の)タブが選択/非表示になったときにも起動されることがわかります。それを回避/検出する方法はありますか?

たぶん、そのバージョンはJTabbedPane、追加/削除の代わりに表示/非表示を使用しますか?更新:詳細な調査によると、コンポーネントは実際には削除されていませんが、タブは非表示になっており、ancestorRemoved()そのためにも起動します。コンポーネントにまだルート*があるかどうかを検出し、ある場合はイベントを無視できますが、問題は、コンポーネントが実際に削除されたときに(非表示のときに)再度起動されないことです。

*まあ、それはまだ分からない。実際に取り外す前に発火したように見えるancestorRemoved()ので、チェーンを上ってgetParent()コンポーネントにルートがあるかどうかを確認することはできません。更新:1ステップ後にを使用してチェックすることで修正されましたSwingUtilities.invokeLater()


ADDED_TO_STAGE(Flash / AS3に精通している人のために、 /REMOVED_FROM_STAGEイベントに相当するSwingを探しています。)

4

2 に答える 2

4

HierarchyListener を使用して修正しました。

public static void addDisplayableListeners(final Component comp, final Runnable onDisplayable, final Runnable onNotDisplayable) {
    comp.addHierarchyListener(new HierarchyListener() {
        @Override public void hierarchyChanged(HierarchyEvent e) {
            System.out.println("HIERARCHY CHANGE ===== " + comp);
            final boolean dc = (e.getChangeFlags() & HierarchyEvent.DISPLAYABILITY_CHANGED) != 0;
            if (dc) {
                System.out.println("DISPLAYABILITY_CHANGED");
                if (comp.isDisplayable()) {
                    onDisplayable.run();
                } else {
                    onNotDisplayable.run();
                }
            }
        }
    });
}

古いバージョン:

    addHierarchyListener(new HierarchyListener() {

        private boolean hadRoot = false;

        @Override public void hierarchyChanged(HierarchyEvent e) {

            System.out.println("HIERARCHY CHANGE ===== " + ContentViewingComponent.this);

            final boolean hasRoot = Swing.hasRoot(ContentViewingComponent.this);
            System.out.println("Has root: " + hasRoot);

            if (hasRoot != hadRoot) {

                System.out.println("...which is not what was.");
                hadRoot = hasRoot;

                if (hasRoot) {
                    log.info("========= Add listeners by " + ContentViewingComponent.this);
                    ...
                } else {
                    log.info("========= Remove listeners by " + ContentViewingComponent.this);
                    ...
                }
            }

        }
    });

注:ここで自分のヘルパー(hadRootおよびhasRoot())を@mKorbelの回答に記載されている公式の方法に置き換えることができるかどうかを調べます。

于 2013-03-21T16:33:55.807 に答える
3

私の意図は、両方のイベント (追加と削除) が基本的にほとんどの状況で一度発生することでした。つまり、コンポーネントが作成されて追加されたときと、削除されて忘れられたときです。

AncestorListener、ComponentListener、および HierarchyListener があり、SwingUtilities を使用してこれらのイベントまたは祖先から getComponent と同じ方法で非同期にすることができます。

例えば

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.event.HierarchyEvent;
import java.awt.event.HierarchyListener;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTabbedPane;
import javax.swing.event.AncestorEvent;
import javax.swing.event.AncestorListener;

public class MyTabbedPane {

    private JTabbedPane tabbedPane = new JTabbedPane();
    private JFrame f = new JFrame();
    private JLabel label1 = new JLabel("Tab1");
    private JLabel label2 = new JLabel("Tab2");
    private JLabel label3 = new JLabel("Tab3");
    private JLabel label4 = new JLabel("Tab4");

    public MyTabbedPane() {
        tabbedPane.addTab("Tab1", label1);
        tabbedPane.addTab("Tab2", label2);
        tabbedPane.addTab("Tab3", label3);
        tabbedPane.addTab("Tab4", label4);
        tabbedPane.setTabPlacement(JTabbedPane.TOP);
        tabbedPane.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT);

        label1.addAncestorListener(new EventHandler());
        label2.addAncestorListener(new EventHandler());
        label3.addAncestorListener(new EventHandler());
        label4.addAncestorListener(new EventHandler());

        label1.addHierarchyListener(new EventHandler());
        label2.addHierarchyListener(new EventHandler());
        label3.addHierarchyListener(new EventHandler());
        label4.addAncestorListener(new EventHandler());

        label1.addComponentListener(new EventHandler());
        label2.addComponentListener(new EventHandler());
        label3.addComponentListener(new EventHandler());
        label4.addComponentListener(new EventHandler());

        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.add(tabbedPane, BorderLayout.CENTER);
        f.setPreferredSize(new Dimension(600, 400));
        f.pack();
        f.setVisible(true);
    }

    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());
                }
            }
        }

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

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

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

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

    public static void main(String args[]) {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                MyTabbedPane frame = new MyTabbedPane();

            }
        });
    }
}
于 2013-03-21T16:21:08.493 に答える