【问题标题】:How do I get images to move without them first jumping to position of the mouse cursor when using mouseDragged?使用 mouseDragged 时,如何在不首先跳转到鼠标光标位置的情况下移动图像?
【发布时间】:2016-04-06 12:11:33
【问题描述】:

我有一个程序,我可以通过单击和拖动在屏幕上移动图像。唯一的问题是,当我单击图像并开始在面板上拖动它时,图像首先会跳转到鼠标光标的位置。我该如何防止这种情况,以便无论我在哪里单击图像,图像都会被简单地移动?我只能让鼠标光标在开始拖动时跳到鼠标箭头下方,或者在开始拖动时跳到鼠标箭头上方,或者设置到要拖动的图像中间。

我正在使用以下函数在另一个类中移动 Image 类的 Image 对象:

moveImage(selected,x,y);

其中 x 和 y 是来自 mouseDragged 方法的坐标。 这是我的图像类:

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

class Image {

    private int x;
    private int y;
    private BufferedImage image;
    private StringBuffer filepath;
    private boolean isTurned;

    public Image(int x, int y, String filepath) throws IOException {
        this.filepath = new StringBuffer(filepath);
        this.x = x;
        this.y = y;
        this.image = ImageIO.read(new File(String.valueOf(filepath)));
    }

    public void draw(Graphics g){

        g.drawImage(image, x, y, null);

    }

    public void undraw (Graphics g, Color c ){
        g.setColor(c);
        g.fillRect(x,y, image.getWidth(), image.getHeight());

    }

    public boolean containsXY (int x, int y){

        if ( (this.x <= x ) && (x <= (this.x+this.image.getWidth())) && (this.y <= y ) && (y <= (this.y+this.image.getHeight()))  ){

            return true;
        }

        return false;
    }

    public void move (Graphics g, int x, int y) {
        System.out.println("int x = " + x + " int y = " + y);
        System.out.println("this x = " + this.x + " this y = " + this.y);
        System.out.println("width: " + this.image.getWidth() + " height: " + this.image.getHeight());

        undraw(g, Color.WHITE);

       /* this.x = x - ((x+image.getWidth())-x);
        this.y = y -((y+image.getHeight())-y);

        this.x = x - (x-this.x);
        this.y = y - (y-this.y);

        this.x = x - (this.x+image.getWidth()-x);
        this.y = y - (this.y+image.getHeight()-y);



        this.x = this.x + (x-image.getWidth());
        this.y = this.y + (y-image.getHeight());

        this.x = x - (image.getWidth());
        this.y = y - (image.getHeight());*/

        this.x = x - (image.getWidth()/2);
        this.y = y - (image.getHeight()/2);


        draw(g);
    }

    public void turn(Graphics g) throws IOException {

        if (isTurned) {
            filepath.replace(filepath.length()-9, filepath.length(), ".gif" );
            undraw(g, Color.WHITE);
            image = ImageIO.read(new File(String.valueOf(filepath)));
            draw(g);
            isTurned = false;
        }

        else {
            filepath.replace(filepath.length()-4, filepath.length(), " back.gif" );
            undraw(g, Color.WHITE);
            image = ImageIO.read(new File(String.valueOf(filepath)));
            draw(g);
            isTurned = true;
        }
    }

}

如您所见,在 move 方法中,我尝试了很多不同的方法来处理传入的鼠标事件拖动坐标。现在在我正在使用的代码中

this.x = x - (image.getWidth()/2);
this.y = y - (image.getHeight()/2);

当我拖动它时,它会使鼠标光标锁定在图像的中间,这是我目前能做的最好的。因此,当我想移动图像并单击图像的一角时,它会“弹出”到图像的中间并在拖动图像时锁定在那里。但我不想要这个。我希望鼠标光标停留在开始拖动时单击的图像上的位置,而不是在其他地方重绘图像然后开始拖动。

这是我调用 Image 对象的类,我在这个类中调用它:s 方法 moveImage:

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;

class PaintSurface extends JLabel implements MouseListener, MouseMotionListener {

    private int x, y;
    private JButton browse;
    private Collection<Image> images = new ArrayList<Image>();
    private final JFileChooser fc = new JFileChooser();
    private Image selected;

    public PaintSurface(JButton b){
        browse = b;
        addMouseListener(this);
        addMouseMotionListener(this);
        browse.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {

                int x = fc.showOpenDialog(browse);

                if (x == JFileChooser.APPROVE_OPTION){
                    try {
                        buttonPressed(fc);

                    } catch (IOException e1) {
                        e1.printStackTrace();
                    }
                }

                else if (x ==JFileChooser.CANCEL_OPTION){
                    System.out.println("No file selected.");
                }
            }
        });
    }

    public void paintComponent (Graphics g){
        super.paintComponent(g);



        for (Image i: images){
            i.draw(g);

        }


    }



    public void addImage(Image i){

        images.add(i);
        Graphics g = getGraphics();
        i.draw(g);

    }

    public void buttonPressed(JFileChooser fc) throws IOException {

        File selectedFile = fc.getSelectedFile();
        String filepath = String.valueOf(selectedFile.getAbsolutePath());
        Image i = new Image(x, y, filepath );
        selected = i;
        addImage(i);
        repaint();

    }

    public Image findImage(int x, int y){

        Image[] imageArray = images.toArray(new Image[images.size()]);

        for (int i = imageArray.length - 1; i >= 0; i--){
            if (imageArray[i].containsXY(x, y)){
                return imageArray[i];
            }
        }
        return null;
    }


    public void moveImage (Image i, int x, int y) { //

        i.move(getGraphics(), x, y);
    }

    public boolean removeImage(Image i){

        Graphics g = getGraphics();
        i.undraw(g, Color.WHITE);
        return images.remove(i);

    }

    @Override
    public void mouseClicked(MouseEvent e) {
        x = e.getX();
        y = e.getY();
        System.out.println("mouseclick");

        selected = findImage(x,y);

        if (selected != null) {

            Graphics g = getGraphics();

            try {
                selected.turn(g);
                repaint();
            } catch (IOException e1) {
                e1.printStackTrace();
            }
            selected = null;
        }

    }

    @Override
    public void mousePressed(MouseEvent e) {
        Image i = findImage(e.getX(), e.getY());

        if (i == null) {

            System.out.println("null mousepress");
            return;

        }

        else {
            System.out.println("not null mousepress");
            if (i == selected){
                return;
            }
            else {
                removeImage(i);
                addImage(i);
                selected = i;

            }


        }






    }

    @Override
    public void mouseDragged(MouseEvent e) {
        int x = e.getX();
        int y = e.getY();

        if (selected != null) {
            moveImage(selected,x,y);
            repaint();
        }
    }

    @Override
    public void mouseReleased(MouseEvent e) {
        selected = null;
    }

    @Override
    public void mouseEntered(MouseEvent e) {

    }

    @Override
    public void mouseExited(MouseEvent e) {

    }

    @Override
    public void mouseMoved(MouseEvent e) {

    }
}

有这方面经验的人可以帮忙吗?大约一个星期以来,我一直在用这个拉头发……

【问题讨论】:

  • 你能贴出你调用 Image 的 move() 方法的代码吗?
  • 感谢您的回答,我更新了代码以显示我调用图像对象方法的类。
  • 请将您的代码减少到重现此问题所需的最低限度。

标签: java


【解决方案1】:

您需要从单击的位置跟踪更改,而不是移动到新的光标位置。在mousePressed中,存储原按位置:

// lastX, lastY are object variables
lastX = e.getX();
lastY = e.getY();

mouseDragged,计算增量

public void mouseDragged(MouseEvent e) {
    int x = i.getX() + e.getX() - lastX;
    int y = i.getY() + e.getY() - lastY;

    if (selected != null) {
        moveImage(selected,x,y);
        repaint();
    }
    lastX = e.getX();
    lastY = e.getY();
}

【讨论】:

  • 非常感谢,我现在意识到问题并不像我想的那样在图像类中。
【解决方案2】:

您可以在 PaintSurface 类中存储 x 和 y 偏移的两个变量,并在 findImage() 方法中初始化它们,如下所示:

if (imageArray[i].containsXY(x, y)){
   xOffset = x - imageArray[i].getX();
   xOffset = y - imageArray[i].getY();
   return imageArray[i];
}

然后你把Image中的move()方法改成

move(Graphics g, int x, int y, int xOffset, int yOffset) {
    undraw(g, Color.WHITE);
    this.x = x - xOffset;
    this.y = y - yOffset;
    draw(g);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-02-05
    • 1970-01-01
    • 1970-01-01
    • 2014-01-06
    • 2020-08-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多