我使用swing写了一个游戏,但我遇到鼠标事件的问题。
我有一个扩展JFrame的Panel,它添加了一个Board对象,其中包含" Paintable"列表中的对象。这些对象包含具有可绘制对象的其他列表,并且它一直调用子对象,直到它到达实际绘制它的最低对象。
public interface Paintable {
void paint(Graphics2D g);
}
我写了一个小例子来说明我的意思:
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.*;
import java.util.List;
public class MainPanel extends JPanel {
List<Patch> patches = new ArrayList<>();
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
MainPanel mainPanel = new MainPanel();
mainPanel.addPatches();
mainPanel.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
System.out.println("out");
// I want to access the clicked object here
}
});
frame.add(mainPanel);
frame.setSize(1000, 800);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
private void addPatches() {
Random random = new Random();
for (int i = 0; i < 100; i++) {
patches.add(new Patch(random.nextInt(1000), random.nextInt(800), 30, 30));
}
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
patches.forEach(patch -> patch.paintComponent(g));
}
}
绘制对象的类:
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
public class Patch extends JComponent {
int x;
int y;
int width;
int height;
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.fillRect(x, y, width, height);
}
public Patch(int x, int y, int width, int height) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
System.out.println("in");
}
});
}
}
我想在mouseClicked事件中访问MainPanel中单击的Patch。我怎么能这样做?
我还尝试在Patch类中添加一个监听器,但这也不起作用。
答案 0 :(得分:2)
如果您检查了Patch组件的大小,您可能会发现它们为0,0或1,1,无论它们是非常小的,因为它们的首选大小非常小。我建议不要让Patch扩展JComponent,而是让它成为一个逻辑非组件实体,并通过使用Shape派生对象,由MainPanel对象保存在集合(如ArrayList)中的对象,并给它鼠标单击属性,以及在添加到MainPanel的MouseListener中被通知可能的鼠标按下。
如,
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.*;
import java.util.List;
@SuppressWarnings("serial")
public class MainPanel extends JPanel {
private static final Color[] COLORS = { Color.red, Color.orange, Color.yellow, Color.blue,
Color.green, Color.cyan, Color.magenta };
private List<Patch> patches = new ArrayList<>();
Random random = new Random();
public MainPanel() {
addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
// use mousePressed not mouseClicked
// go backwards for correct handling of overlaps
for (int i = patches.size() - 1; i >= 0; i--) {
if (patches.get(i).contains(e.getPoint())) {
System.out.println("pressed");
e.consume();
return;
}
}
System.out.println("out");
}
});
}
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
MainPanel mainPanel = new MainPanel();
mainPanel.addPatches();
frame.add(mainPanel);
frame.setSize(1000, 800);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
private void addPatches() {
for (int i = 0; i < 100; i++) {
Color c = COLORS[random.nextInt(COLORS.length)];
patches.add(new Patch(random.nextInt(1000), random.nextInt(800), 30, 30, c));
}
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
patches.forEach(patch -> patch.draw(g));
}
}
class Patch {
private int x;
private int y;
private int width;
private int height;
private Color color;
private Rectangle rectangle;
public Patch(int x, int y, int width, int height, Color color) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.color = color;
rectangle = new Rectangle(x, y, width, height);
}
public boolean contains(Point p) {
return rectangle.contains(p);
}
public void draw(Graphics g) {
Color oldColor = g.getColor();
g.setColor(color);
g.fillRect(x, y, width, height);
g.setColor(oldColor);
}
}