MouseClicked 侦听器不适用于 gui
MouseClicked listener not working with gui
我创建了这个获取鼠标坐标的程序,现在我想添加一个 mouseClicked,它在按下鼠标时在特定坐标处创建一个矩形。但它不起作用。
这是我的代码:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
@SuppressWarnings("serial")
public class GameSetup extends JPanel implements MouseMotionListener {
public static JFrame njf = new JFrame("Test");
public static int x = 0, y = 0;
public static boolean c = false;
public static void main(String[] args) {
GameSetup gs = new GameSetup();
gs.addMouseMotionListener(gs);
njf.add(gs);
njf.setVisible(true);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
this.setBackground(Color.BLACK);
g.setColor(Color.GREEN);
g.drawRect(150, 75, 200, 100);
g.setColor(Color.ORANGE);
g.drawString("Play", 239, 123);
if (x > 150 && y > 75 && x < 350 && y < 175){
g.drawRect(150, 75, 200, 100);
}
if(x > 150 && y > 75 && x < 350 && y < 175 && c){
g.fillRect(10 , 10 ,100 ,100);
}
}
public GameSetup() {
super();
setSize(500, 500);
njf.setSize(500,500);
njf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
njf.setResizable(false);
njf.setLocationRelativeTo(null);
}
@Override
public void mouseDragged(MouseEvent arg0) {
}
@Override
public void mouseMoved(MouseEvent e) {
x = e.getX();
y = e.getY();
if (x > 0 && y > 0) repaint(); else repaint();
}
public void mouseClicked(MouseEvent ea){
c = true;
}
}
我怎样才能完成这项工作?
谢谢
你总不能把 @Override
放在 mouseClicked(...)
上面吧?那是因为您的 class 没有实现正确的接口:MouseListener。也实现此接口,将对象也添加为 MouseListener,您将有权访问 MouseListener 事件。还可以考虑使用您的侦听器方法进行 repaint()
调用,以便 GUI 在必要时重新绘制自身。
我自己的偏好是不让我的视图 classes 也实现我的监听器接口,所以如果这是我的程序,我会创建一个内部 class 扩展 MouseAdapter
并将其用作 MouseListener 和 MouseMotionListener。
其他问题:
- 不要在绘画方法中调用
setBackground
。而是在构造函数中调用它。
- 尽可能避免 "magic" 个数字。
- 考虑使用 JLabel 或 JButton 来完成这项工作,因为您通常最好使用更高级别的构造以便于调试和增强。
例如没有 JLabel...
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.*;
@SuppressWarnings("serial")
public class GameSetup2 extends JPanel {
private static final int PREF_W = 500;
private static final int PREF_H = PREF_W;
private static final Color BG = Color.BLACK;
private static final Color PASSIVE_COLOR = Color.GREEN;
private static final Color ACTIVE_COLOR = Color.ORANGE;
private static final String PLAY = "Play";
private static final int PLAY_X = 239;
private static final int PLAY_Y = 123;
private Rectangle rectangle = new Rectangle(150, 75, 200, 100);
private Color rectColor = PASSIVE_COLOR;
private Color playColor = PASSIVE_COLOR;
public GameSetup2() {
setBackground(BG);
MyMouse myMouse = new MyMouse();
addMouseListener(myMouse);
addMouseMotionListener(myMouse);
// TODO Auto-generated constructor stub
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setColor(playColor);
g2.drawString(PLAY, PLAY_X, PLAY_Y);
g2.setColor(rectColor);
g2.draw(rectangle);
}
@Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
private class MyMouse extends MouseAdapter {
@Override
public void mouseMoved(MouseEvent e) {
if (rectangle.contains(e.getPoint())) {
rectColor = ACTIVE_COLOR;
} else {
rectColor = PASSIVE_COLOR;
}
repaint();
}
@Override
public void mousePressed(MouseEvent e) {
if (rectangle.contains(e.getPoint())) {
playColor = ACTIVE_COLOR;
}
repaint();
}
public void mouseReleased(MouseEvent e) {
playColor = PASSIVE_COLOR;
repaint();
};
}
private static void createAndShowGui() {
GameSetup2 mainPanel = new GameSetup2();
JFrame frame = new JFrame("GameSetup2");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
为了配合 Hovercraft Full Of Eels 所说的内容,我进行了一些重构。注意:
- 实现 MouseListener 或扩展 MouseAdapter,并注册监听器 (
addMouseListener
)
- 变量不需要是 public 或静态的 -- 尝试最小化范围,使用更多封装作为最佳实践
- 添加
repaint()
对 mouseClicked 的调用
- 将
c
更改为 clicked
并使其在 true 和 false 之间切换,因此您可以看到它的变化
试试这个:
public class Game {
public static void main(String[] args) {
final JFrame frame = new JFrame("Test");
frame.setSize(500, 500);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
frame.setLocationRelativeTo(null);
frame.add(new GamePanel());
frame.setVisible(true);
}
@SuppressWarnings("serial")
private static class GamePanel extends JPanel {
private int x = 0;
private int y = 0;
private boolean clicked = false;
public GamePanel() {
super();
setSize(500, 500);
setBackground(Color.BLACK);
addMouseListener(new MouseListenerImpl());
addMouseMotionListener(new MouseMotionListenerImpl());
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.GREEN);
g.drawRect(150, 75, 200, 100);
g.setColor(Color.ORANGE);
g.drawString("Play", 239, 123);
if (x > 150 && y > 75 && x < 350 && y < 175) {
g.drawRect(150, 75, 200, 100);
if (clicked) {
g.fillRect(10, 10, 100, 100);
}
}
}
private class MouseListenerImpl extends MouseAdapter {
@Override
public void mouseClicked(MouseEvent e) {
clicked = !clicked;
repaint();
}
}
private class MouseMotionListenerImpl extends MouseMotionAdapter {
@Override
public void mouseMoved(MouseEvent e) {
x = e.getX();
y = e.getY();
repaint();
}
}
}
}
我创建了这个获取鼠标坐标的程序,现在我想添加一个 mouseClicked,它在按下鼠标时在特定坐标处创建一个矩形。但它不起作用。 这是我的代码:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
@SuppressWarnings("serial")
public class GameSetup extends JPanel implements MouseMotionListener {
public static JFrame njf = new JFrame("Test");
public static int x = 0, y = 0;
public static boolean c = false;
public static void main(String[] args) {
GameSetup gs = new GameSetup();
gs.addMouseMotionListener(gs);
njf.add(gs);
njf.setVisible(true);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
this.setBackground(Color.BLACK);
g.setColor(Color.GREEN);
g.drawRect(150, 75, 200, 100);
g.setColor(Color.ORANGE);
g.drawString("Play", 239, 123);
if (x > 150 && y > 75 && x < 350 && y < 175){
g.drawRect(150, 75, 200, 100);
}
if(x > 150 && y > 75 && x < 350 && y < 175 && c){
g.fillRect(10 , 10 ,100 ,100);
}
}
public GameSetup() {
super();
setSize(500, 500);
njf.setSize(500,500);
njf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
njf.setResizable(false);
njf.setLocationRelativeTo(null);
}
@Override
public void mouseDragged(MouseEvent arg0) {
}
@Override
public void mouseMoved(MouseEvent e) {
x = e.getX();
y = e.getY();
if (x > 0 && y > 0) repaint(); else repaint();
}
public void mouseClicked(MouseEvent ea){
c = true;
}
}
我怎样才能完成这项工作? 谢谢
你总不能把 @Override
放在 mouseClicked(...)
上面吧?那是因为您的 class 没有实现正确的接口:MouseListener。也实现此接口,将对象也添加为 MouseListener,您将有权访问 MouseListener 事件。还可以考虑使用您的侦听器方法进行 repaint()
调用,以便 GUI 在必要时重新绘制自身。
我自己的偏好是不让我的视图 classes 也实现我的监听器接口,所以如果这是我的程序,我会创建一个内部 class 扩展 MouseAdapter
并将其用作 MouseListener 和 MouseMotionListener。
其他问题:
- 不要在绘画方法中调用
setBackground
。而是在构造函数中调用它。 - 尽可能避免 "magic" 个数字。
- 考虑使用 JLabel 或 JButton 来完成这项工作,因为您通常最好使用更高级别的构造以便于调试和增强。
例如没有 JLabel...
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.*;
@SuppressWarnings("serial")
public class GameSetup2 extends JPanel {
private static final int PREF_W = 500;
private static final int PREF_H = PREF_W;
private static final Color BG = Color.BLACK;
private static final Color PASSIVE_COLOR = Color.GREEN;
private static final Color ACTIVE_COLOR = Color.ORANGE;
private static final String PLAY = "Play";
private static final int PLAY_X = 239;
private static final int PLAY_Y = 123;
private Rectangle rectangle = new Rectangle(150, 75, 200, 100);
private Color rectColor = PASSIVE_COLOR;
private Color playColor = PASSIVE_COLOR;
public GameSetup2() {
setBackground(BG);
MyMouse myMouse = new MyMouse();
addMouseListener(myMouse);
addMouseMotionListener(myMouse);
// TODO Auto-generated constructor stub
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setColor(playColor);
g2.drawString(PLAY, PLAY_X, PLAY_Y);
g2.setColor(rectColor);
g2.draw(rectangle);
}
@Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
private class MyMouse extends MouseAdapter {
@Override
public void mouseMoved(MouseEvent e) {
if (rectangle.contains(e.getPoint())) {
rectColor = ACTIVE_COLOR;
} else {
rectColor = PASSIVE_COLOR;
}
repaint();
}
@Override
public void mousePressed(MouseEvent e) {
if (rectangle.contains(e.getPoint())) {
playColor = ACTIVE_COLOR;
}
repaint();
}
public void mouseReleased(MouseEvent e) {
playColor = PASSIVE_COLOR;
repaint();
};
}
private static void createAndShowGui() {
GameSetup2 mainPanel = new GameSetup2();
JFrame frame = new JFrame("GameSetup2");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
为了配合 Hovercraft Full Of Eels 所说的内容,我进行了一些重构。注意:
- 实现 MouseListener 或扩展 MouseAdapter,并注册监听器 (
addMouseListener
) - 变量不需要是 public 或静态的 -- 尝试最小化范围,使用更多封装作为最佳实践
- 添加
repaint()
对 mouseClicked 的调用 - 将
c
更改为clicked
并使其在 true 和 false 之间切换,因此您可以看到它的变化
试试这个:
public class Game {
public static void main(String[] args) {
final JFrame frame = new JFrame("Test");
frame.setSize(500, 500);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
frame.setLocationRelativeTo(null);
frame.add(new GamePanel());
frame.setVisible(true);
}
@SuppressWarnings("serial")
private static class GamePanel extends JPanel {
private int x = 0;
private int y = 0;
private boolean clicked = false;
public GamePanel() {
super();
setSize(500, 500);
setBackground(Color.BLACK);
addMouseListener(new MouseListenerImpl());
addMouseMotionListener(new MouseMotionListenerImpl());
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.GREEN);
g.drawRect(150, 75, 200, 100);
g.setColor(Color.ORANGE);
g.drawString("Play", 239, 123);
if (x > 150 && y > 75 && x < 350 && y < 175) {
g.drawRect(150, 75, 200, 100);
if (clicked) {
g.fillRect(10, 10, 100, 100);
}
}
}
private class MouseListenerImpl extends MouseAdapter {
@Override
public void mouseClicked(MouseEvent e) {
clicked = !clicked;
repaint();
}
}
private class MouseMotionListenerImpl extends MouseMotionAdapter {
@Override
public void mouseMoved(MouseEvent e) {
x = e.getX();
y = e.getY();
repaint();
}
}
}
}