我在 Java 中使用我创建的“canvas”类遇到了问题,该类是一个扩展JPanel
,绘制动画环形图。该图表使用的是MouseListener
获取点击事件。
问题是鼠标位置似乎不准确,这意味着它似乎不是相对于“画布”,而是相对于窗口(在左上角,我得到了大约 30px 的 y 坐标)。
这是我的代码:
我创建了一个类,它扩展了 JPanel 并且有一个 BufferedImage 作为成员。
public class Canvas extends JPanel {
public BufferedImage buf;
private RingChart _parent;
public Canvas(int width, int height, RingChart parent){
buf = new BufferedImage(width, height, 1);
...
在绘画组件方法中,我只绘制缓冲图像,因此我可以通过在公共的缓冲图像上绘画来从“外部”在画布上绘画。
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
g2.drawImage(buf, null, 0, 0);
}
现在有一个包含“画布”的 RingChart 类:
public class RingChart extends JFrame{
public Canvas c;
...
我从画布类中的 bufferedImage 创建一个 Graphics2D 。这个g2d用于绘画:
public RingChart(){
c = new Canvas(1500,980,this);
add(c);
setSize(1500, 1000);
setTitle("Hans");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
g2d = (Graphics2D)c.buf.createGraphics();
...
我现在想要实现的是一个鼠标侦听器,用于侦听画布上发生的鼠标事件。因此,当用户单击画布时,我可以通过事件变量检索他在画布上单击的位置。
所以我创建了一个鼠标监听器:
class MouseHandler implements MouseListener {
@Override
public void mouseClicked(MouseEvent e){
RingChart r = ((Canvas)e.getSource()).getParent();
r.mouseClick(e);
}
...
...并将此鼠标侦听器添加到 RingChart 类的画布中(myChart 是 RingChart 的实例,c 是它包含的画布):
...
MouseHandler mouse = new MouseHandler();
myChart.c.addMouseListener(mouse);
...
但正如我上面提到的,调用单击事件时返回的鼠标位置似乎不准确。我认为错误一定是我创建 mouseListener 的方式,或者可能将其分配给错误的元素或类似的东西。但我已经尝试了很多事情,但情况并没有改变。也许有人可以告诉我,我做错了什么?
UPDATE:
函数“mouseClick”的代码是 RingChart 的成员并在鼠标侦听器中调用:
public void mouseClick(MouseEvent evt){
//evt = SwingUtilities.convertMouseEvent(this, evt, c);
if(evt.getButton() == MouseEvent.BUTTON1 && animation == null){
for(Element e : elements){
if(e.getShape() != null && e.getShape().contains(evt.getPoint())){
//do some stuff
}
}
}
}
再次,我的类的层次结构:
RingChart --包含一个--> Canvas --得到一个--> MouseListener。
该函数中的形状是已经在画布上绘制的形状c。现在我想检查用户是否单击了其中之一。因此,正如我所想,形状应该在画布坐标中,事件位置应该在画布坐标中,并且所有东西都应该配合在一起。但事实并非如此。
现在用户 MadProgrammer 告诉我,使用 ConvertMouseEvent 函数。但我目前不知道应该以哪种方式明智地使用它。
UPDATE:
我找到了一个解决方案:我所要做的就是将画布添加到而不是直接添加到JFrame
但到ContentPane
of the JFrame
反而:
所以与其:
public RingChart(){
c = new Canvas(1500,980,this);
add(c);
...
I do:
public RingChart(){
c = new Canvas(1500,980,this);
getContentPane().add(c);
...
然后我给MouseListener
to the ContentPane
.
getContentPane().addMouseListener(new MouseHandler());
getContentPane().addMouseMotionListener(new MouseMoveHandler());
我不知道这是否是一个优雅的解决方案,但它确实有效。