2013-02-12 3 views
3

Скажем, у меня есть простой JFrame с JTabbedPane, содержащий 3 панели, а вторая панель содержит JComponent. Можно ли уведомлять JComponent, когда панель «Tab 2» удалена из контейнера? Моя проблема в том, что JComponent может быть глубоко в иерархии.Есть ли способ получить уведомление, когда JComponent не отображается больше? Beucase parent удален из коллекции?

Очевидно, что я ищу SWING решение здесь ... :)

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

Я пытался сделать это с ancestorRemoved(), но не повезло ... Я не я, очевидно, делает что-то неправильно .. .

PS. Искусство ASCII сделано с JavE.

ответ

3

Я бы использовать ComponentListener для этой работы (CardLayout так близко, сходный по сравнению с JTabbedPane), пример кода содержит все связанные с ним слушателей (отказ от ответственности -> уведомление блокировки EDT работает только в качестве примера кода и в таком виде только)

Ancesor & HierarchyListener являются немного асинхронной, может быть, есть ваша задача поймать правильное событие из AncestorListener

my question about similar issue

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"); 
    } 
} 
+0

Ну, этот сценарий можно обработать с помощью 'ancestorRemoved()'. Компонент получит это событие, когда пользователь выбирает какой-либо другой дочерний JTabbedPane. Проблема в том, что дочерний элемент JTabbedPane, содержащий компонент, удаляется ... Похоже, что единственный способ быть уведомляется об этом с помощью ContainerListener или адаптера ... – DejanLekic

+0

Спасибо mKorbel, мне нужен был HierarchyListener для случая, когда пользователь удаляет панель. :) – DejanLekic

3

Благодаря mKorbel, который опубликовал хороший пример, где он использует HierarchyListener, я придумал решение, которое, как я считаю, удовлетворяет мои потребности. В этом случае я использую 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 
+0

рад, если поможет вам – mKorbel

3

Если это сам компонент, который должен сделать что-то, вы можете также переопределить добавить/removeNotify (не забудьте позвонить супер хотя

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