簡體   English   中英

在使用mouseDragged時,如何在不先跳到鼠標光標位置的情況下移動圖像?

[英]How do I get images to move without them first jumping to position of the mouse cursor when using mouseDragged?

我有一個程序,可以通過單擊和拖動在屏幕上移動圖像。 唯一的問題是,當我單擊圖像並開始在面板上拖動圖像時,圖像首先跳到鼠標光標的位置。 如何防止這種情況發生,以便無論我在哪里單擊圖像都可以簡單地移動圖像? 我只能使鼠標光標在開始拖動時跳到鼠標箭頭下方,或者在開始拖動時跳到鼠標箭頭上方,或者設置為要拖動圖像的中間位置。

我正在使用以下功能在另一個類中移動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) {

    }
}

有經驗的人可以幫忙嗎? 從大約一個星期以來,我一直在用這種方法拉頭發。

您可以在PaintSurface類中存儲x和y偏移量的兩個變量,並在findImage()方法中將其findImage()如下所示:

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

然后, move() 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);
}

您需要從單擊位置跟蹤更改,而不是移動到新的光標位置。 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();
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM