我有一个小程序,它是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())似乎也无法解决问题。
答案 0 :(得分:3)
如上所述,您应在添加所有组件后致电setVisible(true)
。其他问题:
what structure would you suggest using besides JFrame?
。我建议您很少扩展JFrame,而是将代码设置为创建(或者如果需要,扩展)JPanel。这样做会增加你的类的灵活性,因为现在它可以在GUI中的任何地方使用,包括在JFrame中,在另一个JPanel中,与CardLayout交换,在JApplet中... paintComponent(...)
方法绘制。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()
。答案 1 :(得分:0)
事实证明,正如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
}
}