2014-03-01 72 views
-1

請看看下面的代碼(我已經錯過了故意進口)爲什麼JPanel.focusGaind和Lost不起作用?

public class MainFrame extends JFrame { 
    private JPanel contentPane; 
    public static void main(String[] args) { 
     EventQueue.invokeLater(new Runnable() { 
      public void run() { 
       try { 
        MainFrame frame = new MainFrame(); 
        frame.setVisible(true); 
       } catch (Exception e) { 
        e.printStackTrace(); 
       } 
      } 
     }); 
    } 
    public MainFrame() { 
     setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     setBounds(100, 100, 450, 300); 
     contentPane = new JPanel(); 
     contentPane.setBorder(new EmptyBorder(5, 5, 5, 5)); 
     setContentPane(contentPane); 
     contentPane.setLayout(null); 
     JTabbedPane tabbedPane = new JTabbedPane(JTabbedPane.TOP); 
     tabbedPane.setBounds(10, 11, 414, 240); 
     contentPane.add(tabbedPane); 
     JPanel panel = new JPanel(); 
     panel.addFocusListener(new FocusListener() { 

      @Override 
      public void focusLost(FocusEvent arg0) { 
       System.out.println("lost"); 
       // I want to do something here, if I reach here! 
      } 

      @Override 
      public void focusGained(FocusEvent arg0) { 
       System.out.println("gained"); 
       // I want to do something here, if I reach here! 
      } 
     }); 
     tabbedPane.addTab("New tab", null, panel, null); 
     JButton button = new JButton("New button"); 
     panel.add(button); 
     JPanel panel_1 = new JPanel(); 
     tabbedPane.addTab("New tab", null, panel_1, null); 
     JPanel panel_2 = new JPanel(); 
     tabbedPane.addTab("New tab", null, panel_2, null); 
    } 
} 

我創建這個類來測試它,然後添加onFocusListener在我主要的代碼,但它不工作的我期望的方式。請說出有什麼不對,或者這是否是正確的EvenetListener?

+0

@Downvoters:你能告訴我從我的錯誤中學習的理由是什麼? – mok

回答

4
  1. 默認情況下,JPanels不可聚焦。如果您想要使用FocusListener,您首先必須通過setFocusable(true)更改此屬性。
  2. 但即使你這樣做,FocusListener不是你想要的。
  3. 相反,我希望聽聽JTabbedPane模型的變化。它使用SingleSelectionModel,您可以將ChangeListener添加到此模型,偵聽更改,檢查當前顯示的組件以及組件是否響應。
  4. 您正在使用setBounds和null佈局,如果您計劃創建和維護玩具Swing程序以外的任何東西,則您將不希望這樣做。

編輯
例如:

import java.awt.BorderLayout; 
import java.awt.Component; 
import java.awt.Dimension; 
import javax.swing.*; 
import javax.swing.event.*; 

@SuppressWarnings("serial") 
public class MainPanel extends JPanel { 
    private static final int PREF_W = 450; 
    private static final int PREF_H = 300; 
    private static final int GAP = 5; 
    private static final int TAB_COUNT = 5; 

    private JTabbedPane tabbedPane = new JTabbedPane(); 

    public MainPanel() { 
     for (int i = 0; i < TAB_COUNT; i++) { 
     JPanel panel = new JPanel(); 
     panel.add(new JButton("Button " + (i + 1))); 
     panel.setName("Panel " + (i + 1)); 
     tabbedPane.add(panel.getName(), panel);   
     } 

     setBorder(BorderFactory.createEmptyBorder(GAP, GAP, GAP, GAP)); 
     setLayout(new BorderLayout()); 
     add(tabbedPane, BorderLayout.CENTER); 

     tabbedPane.getModel().addChangeListener(new ChangeListener() { 

     @Override 
     public void stateChanged(ChangeEvent evt) { 
      Component component = tabbedPane.getSelectedComponent(); 
      System.out.println("Component Selected: " + component.getName()); 
     } 
     }); 
    } 

    @Override 
    public Dimension getPreferredSize() { 
     return new Dimension(PREF_W, PREF_H); 
    } 

    private static void createAndShowGui() { 
     MainPanel mainPanel = new MainPanel(); 

     JFrame frame = new JFrame("MainPanel"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.getContentPane().add(mainPanel); 
     frame.pack(); 
     frame.setLocationByPlatform(true); 
     frame.setVisible(true); 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 
     public void run() { 
      createAndShowGui(); 
     } 
     }); 
    } 
} 
2

JPanel是一個輕量級的容器,它是不是一個可操作的組件,因此它不會焦點事件。它允許您添加焦點偵聽器,因爲擺動組件層次結構。爲了獲取選項卡選定的事件,您需要使用JTabbedPane#addChangeListener

希望這會有所幫助。