MouseEvent getX和getY偏离实际坐标

时间:2015-11-19 03:57:02

标签: java swing mouseevent

我编写了一个基本的绘图程序,但我在使用RectangleEllipse工具时遇到了问题。如果单击并拖动,您应该能够使用基于startpointendpoint(均使用getX()getY())的维度绘制形状,问题在于这两个形状得到startpoint,但endpoint在x和y坐标都是偏移的。

以下代码与我在线条工具中使用的代码(工作正常)几乎相同,只是分别用Line2DRectangle2D交换Ellipse2D

package tools;

import gui.DrawingPanel;

import java.awt.event.ActionEvent;

import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Rectangle2D;

import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.ImageIcon;


/**
 * Creates the Rectangle Action.
 *@version 1
 */
public class RectangleAction extends AbstractAction {

    private final DrawingPanel myPanel;

    private Rectangle2D.Double myRectangle;
    private double Start_X;
    private double Start_Y;

    /**
     * Constructor for Rectangle Action.
     */
    public RectangleAction(final DrawingPanel thePanel) {
        super("Rectangle", getImageIcon()); 

        myPanel = thePanel;
        putValue(Action.MNEMONIC_KEY, KeyEvent.VK_R);
        putValue(Action.SELECTED_KEY, true);
    }

    @Override
    public void actionPerformed(final ActionEvent theEvent) {

        myPanel.addMouseListener(new MyMouseListener());
        myPanel.addMouseMotionListener(new MyMouseListener());

    }

    /**
     * gets the image icon of the action.
     * @return the image icon.
     */
    public static ImageIcon getImageIcon() {
        return new ImageIcon("./images/rectangle.gif");
    }    


    /**
     * Listens for mouse clicks, to draw on our panel.
     */
    private class MyMouseListener extends MouseAdapter {


        private double myX2;
        private double myY2;               


        /**
         * Handles a click event.
         * 
         * @param theEvent The event.
         */
        @Override
        public void mousePressed(final MouseEvent theEvent) {


            Start_X = (double) theEvent.getX();
            Start_Y = (double) theEvent.getY();
        }

        /**
         * Handles the release event.
         * 
         * @param theEvent The event.
         */
        @Override
        public void mouseReleased(final MouseEvent theEvent) {

            myX2 = (double) theEvent.getX();
            myY2 = (double) theEvent.getY();

            myRectangle = new Rectangle2D.Double(Start_X, Start_Y, myX2, myY2);

            myPanel.setShape(myRectangle);
            myPanel.repaint();           

        }

        /**
         * Handles a click event.
         * 
         * @param theEvent The event.
         */
        @Override
        public void mouseDragged(final MouseEvent theEvent) {

            myX2 = (double) theEvent.getX();
            myY2 = (double) theEvent.getY();

            myRectangle = new Rectangle2D.Double(Start_X, Start_Y, myX2, myY2);                                                                                          

            myPanel.setShape(myRectangle);
            myPanel.repaint();           

        }

    }

}

enter image description here

我应该注意到我确实看过this similar question,但它并没有给我我想要的答案;同样DrawingPanel只是一个JPanel,它有一个Paint Component来绘制形状,而不是其他任何东西。

2 个答案:

答案 0 :(得分:4)

myRectangle = new Rectangle2D.Double(Start_X, Start_Y, myX2, myY2);

您尝试指定两个点的参数是(x,y,width,height)。

您的绘画逻辑假定您始终将鼠标从顶部/左侧拖动到底部/右侧。鼠标总是可以向上和向左拖动,这会在您根据两点计算宽度/高度时产生负值。

这是我用来正确计算矩形边界的代码:

int x = Math.min(startPoint.x, e.getX());
int y = Math.min(startPoint.y, e.getY());
int width = Math.abs(startPoint.x - e.getX());
int height = Math.abs(startPoint.y - e.getY());

您不需要创建两个侦听器,您可以只共享同一个侦听器:

//myPanel.addMouseListener(new MyMouseListener());
//myPanel.addMouseMotionListener(new MyMouseListener());
MouseAdapter myMouseAdapter = new MyMouseListener();
myPanel.addMouseListener( myMouseAdapter );
myPanel.addMouseMotionListener( myMouseAdapter);

此外,每次单击按钮时,都会继续将适配器添加到面板中。因此,如果您单击线工具,然后是ellispse工具,然后是矩形工具,您将在面板中添加3个侦听器。我建议您在添加当前工具的监听器之前从面板中删除所有监听器。

答案 1 :(得分:3)

您正在使用x和y版本而不是宽度和高度初始化矩形。

替换

myRectangle = new Rectangle2D.Double(Start_X, Start_Y, myX2, myY2);

        int x;
        int y;
        if (Start_X > myX2) {
            x = myX2;
        } else {
            x = Start_X;
        }
        if (Start_Y > myY2) {
            y = myY2;
        } else {
            y = Start_Y;
        }
        myRectangle = new Rectangle2D.Double(x, y, Math.abs(myX2 - Start_X), Math.abs(myY2 - Start_Y));
相关问题