如何在我的 mouseDragged 事件中访问 ImageIcons

How to access ImageIcons in my mouseDragged event

我正在尝试弄清楚如何在我的事件中访问使用 paintComponent 绘制的不同图像(在作业中不允许使用 JLabel)。

拖动时,我只想用鼠标拖动移动一个图像,我似乎无法使用 e.getSource() 访问 "current image"。

我的 paintComponent 将同时移动所有 (3) 个图像。

我的问题是:如何使用我的 mouseDragged 获取单个 ImageIcon?

public class PhotoPanel extends JPanel implements MouseListener, MouseMotionListener {

private java.util.List<ImageIcon> myList = new ArrayList<>();
private int mx, my;

private ImageIcon image1 = new ImageIcon("src/resources/gira.gif");
private ImageIcon image2 = new ImageIcon("src/resources/stru.gif");
private ImageIcon image3 = new ImageIcon("src/resources/back.gif"); 

public PhotoPanel()
{
    setBackground(Color.GREEN);

    myList.add(image1);
    myList.add(image2);
    myList.add(image3);

    //Is this a problematic way of doin it?
    addMouseMotionListener(this);

}

public void paintComponent (Graphics g) {

    super.paintComponent(g);

    for (ImageIcon i : myList)
    {
       g.drawImage(i.getImage(), mx, my, this);
    }    
}


@Override
public void mouseDragged(MouseEvent e) {

    //if(e.getSource == image1)
    //{
    //    Manipulate single picture, but not working this way  
    //}
    mx = e.getX();
    my = e.getY();

    repaint();
    }    
}

不要绘制图像,使用 JLabels 来显示它们。

JLabel imageLabel1 = new JLabel(image1);

如果将此添加到您的面板,它将显示您的图像。您可以通过触及标签来触及您的形象。顺便说一下,将您的侦听器添加到所有标签,这样 getSource() 就会 return 为您添加相关标签。

我发现代码的几个部分存在问题。首先,您的图像将始终绘制在另一张之上,因为

for (ImageIcon i : myList)
{
   g.drawImage(i.getImage(), mx, my, this);
}

mxmy 用于所有图像。所以你需要每张图片都有自己的坐标。

您缺少的另一部分是用于确定首次单击鼠标时鼠标下方是什么图像的代码。您可能需要获取图像的宽度和高度(然后计算另一个角的位置),但是之后,确定点击 x y 是否在矩形图像的边界内是简单的数学运算。请注意,您需要为所有三张图片确定这一点。


关于 getSource() 你需要意识到的是 returns 行中的隐式参数 addMouseMotionListener(this);

你的 JPanel 监听自己也有点奇怪。

I'm trying to figure out how to access my different images, drawn with paintComponent, (using JLabels is not allowed in the assignment) in my events

因为你不能使用JLabels,如果你想获得当前被选中的图像。您将不得不遍历图像列表添加检查选择了哪一个。

目前您保留了一个 ImageIcon 列表,没有直接方法获取 ImageIcon 的边界以检查选择。

如果我是你,我会在当前的ImageIcon上加一个属性(bounds),方便我们判断图片是否被鼠标点击:

class MyImages extends Rectangle
{
    private ImageIcon image;  //personally, I prefer to use BufferedImage here

    public MyImages(int x, int y, int width, int height){
        setBounds(x, y, width, height);
    }

    //getters & setters for image not shown

    public void draw(Graphics g){
        g.drawImage(image.getImage(), x, y, width, height, null);
    }

    //Check if current image is selected:
    public boolean isSelected(int xCoord, int yCoord){
        return (this.contains(xCoord, yCoord))
    }
}

在您的照片面板中 class:

//Crate a list of MyImage instead of ImageIcon
ArrayList<MyImage> myList = new ArrayList<MyImage>();
MyImage selectedImage;

在你的MouseMotionListener中class:

@Override 
public void mousePressed(MouseEvent e){

    //To get the image which is selected:
    for(MyImage img : myList)
        if(img.isSelected(e.getX(), e.getY())){  //if mouse clicks on this image
            selectedImage = img;    
            break;
        }
}

@Override
public void mouseDragged(MouseEvent e){
    if(selectedImage != null){
        selectedImage .setLocation(e.getX()-(pieceWH/2), e.getY()-(pieceWH/2));
        repaint();
    }
}

我维护一个调用 selectedImage 的实例,在鼠标拖动时,我们将仅更改 selectedImage 的位置。因此只有最后选择的图像会移动。


在您的 paintComponent(g) 方法中,如果您创建了自定义图像 class,例如 MyImage:

,您可以只使用 .draw(g)
@Override
protected void paintComponent(Graphics g){
    super.paintComponent(g);
    for (MyImage i : myList)
        i.draw(g);
}

这是我以前用同样的技巧做的拼图: