java swing 如何获取鼠标的实时位置?
How to get the live location of mouse in java swing?
我正在尝试创建一个简单的井字游戏,我想在鼠标所在的方块上显示高亮显示。我在 java.awt.Canvas
上画了游戏,目前,我尝试了这些失败的方法:
- 我试图将
MouseAdapter
添加到我的 Canvas 并覆盖其 mouseEnter
方法,但它仅在光标进入 Canvas(正如它应该的那样)。
- 然后我添加了 9 个
JPanel
s(每个方格一个)并为每个添加了一个 MouseAdapter
。但它也没有用。我搜索了原因,发现我应该 requestFocus()
启用侦听器。
顺便说一句,这是我的代码:
Class 用于覆盖 MouseAdaper
的方法:
public class MouseInput extends MouseAdapter {
private final Game game;
private final int i;
private final int j;
public MouseInput(Game game, JPanel panel){
this.game = game;
i = panel.getY() / 64;
j = panel.getX() / 64;
}
@Override
public void mouseEntered(MouseEvent e) {
game.mouseEntered(i, j);
}
@Override
public void mouseExited(MouseEvent e) {
game.mouseExited(i, j);
}
@Override
public void mouseClicked(MouseEvent e){
game.mouseClicked(i, j);
}
}
游戏中 JPanel
s 并向其添加 MouseListener
:
public class Game extends Canvas implements Runnable {
private boolean isRunning = false;
private Thread thread;
private final JPanel[][] panels = new JPanel[3][3];
public static void main(String[] args) {
Game game = new Game();
game.setPreferredSize(new Dimension(192, 192));
JFrame frame = new JFrame();
frame.add(game);
frame.setResizable(false);
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
game.start();
}
private void start(){
if(isRunning){
return;
}
isRunning = true;
thread = new Thread(this);
thread.start();
}
private void stop(){
if(!isRunning){
return;
}
isRunning = false;
try {
thread.join();
} catch (InterruptedException ignored) {}
System.exit(0);
}
@Override
public void run(){
for(int i = 0; i < 3; i++){
for(int j = 0; j < 3; j++){
JPanel p = new JPanel();
p.setPreferredSize(new Dimension(64, 64));
p.setLocation(j * 64, i * 64);
p.addMouseListener(new MouseInput(this, p));
panels[i][j] = p;
}
}
}
}
Swing 不是线程安全的,而是单线程的。您不应该更新 UI 或更新 UI 依赖于事件调度线程上下文之外的内容。
在您的情况下,面板实际上并未附加到任何东西(即添加到容器),因此无法响应任何事件。
您还应该花时间学习一些布局管理基础知识。
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.LineBorder;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
JFrame frame = new JFrame();
JPanel board = new JPanel(new GridLayout(3, 3));
for (int index = 0; index < 9; index++) {
board.add(new GridPane());
}
frame.add(board);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class GridPane extends JPanel {
private MouseListener mouseHandler;
public GridPane() {
setBorder(new LineBorder(Color.BLACK));
}
@Override
public Dimension getPreferredSize() {
return new Dimension(50, 50);
}
@Override
public void addNotify() {
super.addNotify();
if (mouseHandler != null) {
removeMouseListener(mouseHandler);
}
mouseHandler = new MouseAdapter() {
@Override
public void mouseEntered(MouseEvent e) {
setBackground(Color.RED);
}
@Override
public void mouseExited(MouseEvent e) {
setBackground(null);
}
};
addMouseListener(mouseHandler);
}
@Override
public void removeNotify() {
super.removeNotify();
if (mouseHandler != null) {
removeMouseListener(mouseHandler);
}
}
}
}
而不是试图让一个听众尝试更新游戏模型。将游戏引用传递给每个面板并让它完成这项工作。通过这种方式,您可以将“标识符”传递给每个可以传递回游戏的单元格,以便它可以做出一些需要的决定。
我正在尝试创建一个简单的井字游戏,我想在鼠标所在的方块上显示高亮显示。我在 java.awt.Canvas
上画了游戏,目前,我尝试了这些失败的方法:
- 我试图将
MouseAdapter
添加到我的 Canvas 并覆盖其mouseEnter
方法,但它仅在光标进入 Canvas(正如它应该的那样)。 - 然后我添加了 9 个
JPanel
s(每个方格一个)并为每个添加了一个MouseAdapter
。但它也没有用。我搜索了原因,发现我应该requestFocus()
启用侦听器。
顺便说一句,这是我的代码:
Class 用于覆盖 MouseAdaper
的方法:
public class MouseInput extends MouseAdapter {
private final Game game;
private final int i;
private final int j;
public MouseInput(Game game, JPanel panel){
this.game = game;
i = panel.getY() / 64;
j = panel.getX() / 64;
}
@Override
public void mouseEntered(MouseEvent e) {
game.mouseEntered(i, j);
}
@Override
public void mouseExited(MouseEvent e) {
game.mouseExited(i, j);
}
@Override
public void mouseClicked(MouseEvent e){
game.mouseClicked(i, j);
}
}
游戏中 JPanel
s 并向其添加 MouseListener
:
public class Game extends Canvas implements Runnable {
private boolean isRunning = false;
private Thread thread;
private final JPanel[][] panels = new JPanel[3][3];
public static void main(String[] args) {
Game game = new Game();
game.setPreferredSize(new Dimension(192, 192));
JFrame frame = new JFrame();
frame.add(game);
frame.setResizable(false);
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
game.start();
}
private void start(){
if(isRunning){
return;
}
isRunning = true;
thread = new Thread(this);
thread.start();
}
private void stop(){
if(!isRunning){
return;
}
isRunning = false;
try {
thread.join();
} catch (InterruptedException ignored) {}
System.exit(0);
}
@Override
public void run(){
for(int i = 0; i < 3; i++){
for(int j = 0; j < 3; j++){
JPanel p = new JPanel();
p.setPreferredSize(new Dimension(64, 64));
p.setLocation(j * 64, i * 64);
p.addMouseListener(new MouseInput(this, p));
panels[i][j] = p;
}
}
}
}
Swing 不是线程安全的,而是单线程的。您不应该更新 UI 或更新 UI 依赖于事件调度线程上下文之外的内容。
在您的情况下,面板实际上并未附加到任何东西(即添加到容器),因此无法响应任何事件。
您还应该花时间学习一些布局管理基础知识。
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.LineBorder;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
JFrame frame = new JFrame();
JPanel board = new JPanel(new GridLayout(3, 3));
for (int index = 0; index < 9; index++) {
board.add(new GridPane());
}
frame.add(board);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class GridPane extends JPanel {
private MouseListener mouseHandler;
public GridPane() {
setBorder(new LineBorder(Color.BLACK));
}
@Override
public Dimension getPreferredSize() {
return new Dimension(50, 50);
}
@Override
public void addNotify() {
super.addNotify();
if (mouseHandler != null) {
removeMouseListener(mouseHandler);
}
mouseHandler = new MouseAdapter() {
@Override
public void mouseEntered(MouseEvent e) {
setBackground(Color.RED);
}
@Override
public void mouseExited(MouseEvent e) {
setBackground(null);
}
};
addMouseListener(mouseHandler);
}
@Override
public void removeNotify() {
super.removeNotify();
if (mouseHandler != null) {
removeMouseListener(mouseHandler);
}
}
}
}
而不是试图让一个听众尝试更新游戏模型。将游戏引用传递给每个面板并让它完成这项工作。通过这种方式,您可以将“标识符”传递给每个可以传递回游戏的单元格,以便它可以做出一些需要的决定。