【问题标题】:JFrame MouseListener does not workJFrame MouseListener 不起作用
【发布时间】:2014-06-06 18:05:10
【问题描述】:

我有一个子类 JFrame 的小程序。代码如下:

package complexviewer;  

import java.awt.*;  
import java.awt.event.*;    
import java.util.concurrent.*;  
import static java.util.concurrent.TimeUnit.*;  
import javax.swing.*;   

public class Applet extends JFrame {    

    // Window and applet stats  
    public static final int windowSize = 400;   
    public static final int updateDelay = 20;   

    // Instance variables   
    private ScheduledExecutorService timer = Executors.newScheduledThreadPool(1);   

    public static void main(String[] args) {    
        new Applet();   
    }   
    public Applet() {   
        // Set up window    
        super("Complex Viewing Frame"); 
        setSize(windowSize, windowSize);    
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

        setVisible(true);

        // Add listeners    
        JPanel panel = new JPanel();    
        panel.setFocusable(true);   
        panel.addKeyListener(new KeyListener() {    
            public void keyPressed(KeyEvent key) {  
                System.out.println("Key pressed."); 
            }   
            public void keyReleased(KeyEvent key) {}    
            public void keyTyped(KeyEvent key) {}   
        }); 
        panel.addMouseListener(new MouseListener() {    
            public void mouseReleased(MouseEvent mouse) {}  
            public void mouseClicked(MouseEvent mouse) {}   
            public void mousePressed(MouseEvent mouse) {    
                System.out.println("Mouse clicked.");   
            }   
            public void mouseEntered(MouseEvent mouse) {}   
            public void mouseExited(MouseEvent mouse) {}    
        }); 
        panel.addMouseMotionListener(new MouseMotionListener() {    
            public void mouseDragged(MouseEvent mouse) {    
                System.out.println("Mouse dragged.");   
            }   
            public void mouseMoved(MouseEvent mouse) {} 
        }); 
        add(panel); 
        panel.requestFocus();   

        timer.scheduleAtFixedRate(() -> repaint(), 0, 200, MILLISECONDS);   
    }   

    public void paint(Graphics G) { 
        // Drawing  
    }   

}

当我运行它时,“按键”事件工作正常,但鼠标事件都不起作用。我在这里想念什么?我查看了其他答案,例如

此外,选择不同的组件,如 getContentPane() 似乎也不能解决问题。

【问题讨论】:

  • "I have an applet which subclasses JFrame..." -- 必须扩展 Applet 或 JApplet 的 applet 类不能“继承 JFrame”。请澄清。你班级的名字真的是“Applet”吗?这让人困惑到了极点。不要那样做。
  • 这一行:timer.scheduleAtFixedRate(() -> repaint(), 0, 200, MILLISECONDS); 表明您在绘画方法中有代码,无论是paint 还是paintComponent,它都会更改此类的状态。您不想这样做,因为您无法控制何时或是否调用这些方法,并且您不想减慢绘制方法的速度。同样,发布您的最小代码示例
  • ... 在添加所有组件之前,您不应调用 setVisible(true)。仅在添加所有组件后调用它。如果您真的需要帮助,请再次创建并发布您的 minimal example program
  • @HovercraftFullOfEels 对于这个(简单的,只是绘制和接收键盘/鼠标事件)应用程序,除了 JFrame,您还建议使用什么结构?使用 JApplet 有什么好处?还是您只是说将其称为“小程序”会令人困惑?

标签: java swing jframe mouselistener


【解决方案1】:

如上所述,您应该在添加所有组件后调用setVisible(true)。其他问题:

  • 不要将您的非小程序 GUI 命名为“Applet”,因为该名称与常用的核心 Java 类冲突,这会使其他审查您的工作的人非常困惑。你的类不是一个小程序,即使它是,也应该被称为别的东西。
  • 你问,what structure would you suggest using besides JFrame?。我建议您很少扩展 JFrame,而是将代码用于创建(或如果需要,扩展)JPanel。这样做会增加类的灵活性,因为现在它可以在 GUI 中的任何位置使用,包括在 JFrame、另一个 JPanel、与 CardLayout 交换、在 JApplet 中......
  • 永远不要直接在 JFrame 中进行绘制。
  • 改为扩展 JPanel 并在其 paintComponent(...) 方法中绘制。
  • 您没有显示您的绘画代码,但由于您在 Timer 中重复调用 repaint,而该计时器不执行任何其他操作,这表明您的类的状态在绘画方法中发生了更改, 永远不会发生的事情,因为您无法完全控制何时或什至何时调用绘画方法。
  • 你说,According to this question, a javax.swing.Timer, which I heard was deprecated as I should use ScheduledExecutorService instead. 这是非常错误的。您应该使用 Swing Timer 来满足 Swing 计时器的需求,而不是 java.util.Timer。这些人都没有被弃用,但我在非 Swing 应用程序中使用 ScheduledExecutorService 而不是 java util Timer。
  • 计时器代码应该更改类的状态然后调用repaint()
  • 您会希望使用键绑定而不是 KeyListener。一方面,您可以避免强制 JPanel 或 JFrame 获得键盘焦点的麻烦。

【讨论】:

    【解决方案2】:

    事实证明,正如 Hovercraft Full of Eels 所建议的那样,问题在于 setVisible(true)add(panel) 之前被调用。移动此语句允许所有侦听器正常工作。工作代码的可编译示例如下:

    package complexviewer;  
    
    import java.awt.*;  
    import java.awt.event.*;    
    import java.util.concurrent.*;  
    import static java.util.concurrent.TimeUnit.*;  
    import javax.swing.*;   
    
    public class Applet extends JFrame {    
    
        // Window and applet stats  
        public static final int windowSize = 400;   
        public static final int updateDelay = 20;   
    
        // Instance variables   
        private ScheduledExecutorService timer = Executors.newScheduledThreadPool(1);   
    
        public static void main(String[] args) {    
            new Applet();   
        }   
        public Applet() {   
            // Set up window    
            super("Complex Viewing Frame"); 
            setSize(windowSize, windowSize);    
            setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    
            // Incorrect location for setVisible    
    
            // Add listeners    
            JPanel panel = new JPanel();    
            panel.setFocusable(true);   
            panel.addKeyListener(new KeyListener() {    
                public void keyPressed(KeyEvent key) {  
                    System.out.println("Key pressed."); 
                }   
                public void keyReleased(KeyEvent key) {}    
                public void keyTyped(KeyEvent key) {}   
            }); 
            panel.addMouseListener(new MouseListener() {    
                public void mouseReleased(MouseEvent mouse) {}  
                public void mouseClicked(MouseEvent mouse) {}   
                public void mousePressed(MouseEvent mouse) {    
                    System.out.println("Mouse clicked.");   
                }   
                public void mouseEntered(MouseEvent mouse) {}   
                public void mouseExited(MouseEvent mouse) {}    
            }); 
            panel.addMouseMotionListener(new MouseMotionListener() {    
                public void mouseDragged(MouseEvent mouse) {    
                    System.out.println("Mouse dragged.");   
                }   
                public void mouseMoved(MouseEvent mouse) {} 
            }); 
            add(panel); 
            panel.requestFocus();   
    
            setVisible(true); // Correct location for setVisible    
    
            timer.scheduleAtFixedRate(() -> repaint(), 0, 200, MILLISECONDS);   
        }   
    
        public void paint(Graphics G) { 
            // Drawing  
        }   
    
    }   
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-20
      • 1970-01-01
      • 2015-09-29
      • 2014-01-30
      • 1970-01-01
      • 2016-04-07
      相关资源
      最近更新 更多