为什么 JPanel.focusGaind 和 Lost 不起作用?

mok*_*mok 0 java events swing jpanel

请看下面的代码(我故意错过了导入)

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

我创建了这个类来测试它,然后在我的主代码中添加 onFocusListener,但它没有按我预期的方式工作。请告诉有什么问题,或者这是正确的 EventetListener 吗?

Hov*_*els 6

  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();
         }
      });
   }
}
Run Code Online (Sandbox Code Playgroud)