2013-03-21 5 views
2

Я использую следующий код, чтобы позволить моему компоненту регистрировать/отменять регистрацию событий, когда он добавлен/удален соответственно.Swing AncestorListener: Не запускать для переключения вкладок?

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

Моя цель в том, что оба события (добавлять и удалять) будет в основном стрелять один раз в большинстве случаев, то есть при создании компонента & добавляется и когда он удален & забыл.

Однако выясняется, что они также запускаются, когда вкладка (JTabbedPane), в которой находится этот компонент, выбрана/скрыта. Есть ли способ обходить/обнаруживать это?

Возможно, версия JTabbedPane, использующая отображение/скрытие вместо добавления/удаления? Обновление: больше исследований показывает, что компонент фактически не удален, но скрытая вкладка и ancestorRemoved() тоже срабатывает. Я могу определить, есть ли у компонента еще один корень * и игнорировать событие, если он есть, но проблема в том, что он не будет запущен снова, когда компонент фактически будет удален (пока он невидим).

* Ну, это еще предстоит выяснить. Оказывается, ancestorRemoved() срабатывает перед фактическим удалением, поэтому я не могу подойти к цепи getParent(), чтобы узнать, имеет ли компонент корень. Обновление: Исправлено, проверив его на один шаг позже, используя SwingUtilities.invokeLater().


(Для тех, кто знаком с Flash/AS3, я ищу для свинг эквивалента ADDED_TO_STAGE/REMOVED_FROM_STAGE событий.)

+0

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

+0

@ GilbertLeBlanc Да, но есть проблема. Я могу игнорировать событие, которое просто означает «невидимое», но если компонент затем удаляется (хотя и невидим), он не дает мне знать. –

ответ

1

Моя цель в том, что оба события (добавление и удаление) будет в основном огонь один раз в большинстве случаев, т.е. когда компонент создается & добавил и когда он удален & забыл

есть AncestorListener, ComponentListener и HierarchyListener и могут быть асинхронными, одни и те же способы, вы можете GetComponent, из этих событий или предка с помощью SwingUtilities

, например

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

      } 
     }); 
    } 
} 
+0

Тем временем я «исправил» его (см. Мой собственный ответ), но я также могу включить некоторые элементы из этого ответа. –

3

Фиксированный с помощью 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 отвечают.