1

所以我基本上正在开发一个交易或没有交易的java游戏,现在我正试图让图像图标在用户点击的地方消失。所以我有一个 6 x 6 的“金属公文包”(casesArray)图像图标数组,但无论用户点击哪里,只有左上角的图像图标会消失。我猜这只是我的一个逻辑错误,但我似乎无法弄清楚我做错了什么......

class MouseClickListener implements MouseListener
    {
        public void mouseClicked (MouseEvent event)
        {
            if (event.getX() <= 133)row=0;
            else if (event.getX() <= 267 && event.getX()>133)row=1;
            else if (event.getX() <= 400 && event.getX()>267)row=2;
            else if (event.getX() <= 533 && event.getX()>400)row=3;
            else if (event.getX() <= 667 && event.getX()>533)row=4;
            else if (event.getX() <= 800 && event.getX()>667)row=5;
             if (event.getY() <= 100)column=0;
            else if (event.getY() <= 200 && event.getY() > 100)column=1;
            else if (event.getY() <= 300 && event.getY() > 200)column=2;
            else if (event.getY() <= 400 && event.getY() > 300)column=3;
            else if (event.getY() <= 500 && event.getY() > 400)column=4;
            else if (event.getY() <= 600 && event.getY() > 500)column=5;

            casesArray[row][column].setIcon(null);
            repaint();
        }
    .
    .
    .
    .
for(int i=0; i<6; i++)
    {
        for(int j=0; j<6; j++)
        {
            casesArray[i][j].addMouseListener(new MouseClickListener());
        }
    }
4

3 回答 3

1

MouseEvents 与引发它们的组件相关。也就是说,事件的 x/y 点会自动转换为发生事件的组件的坐标空间。

因此,如果一个组件存在于其父级中的 100x100 处,当您单击它时,鼠标事件将被转换为坐标为 0x0,表示被单击组件的顶层角。

尝试直接直接引用组件,而不是使用一系列if语句...

class MouseClickListener implements MouseListener
{
    public void mouseClicked (MouseEvent event)
    {
        Component comp = event.getComponent();
        if (comp instanceof JLabel) {
            ((JLabel)comp).setIcon(null);
        }
    }
}

更新了其他示例

MouseEvent#getSource返回对创建事件的对象的引用...

class MouseClickListener implements MouseListener
{
    public void mouseClicked (MouseEvent event)
    {
        Object source = event.getSource();
        for (int x = 0; x < casesArray.length; x++) {
            for (int y = 0; y < casesArray[x].length; y++) {
                if (casesArray[x][y] == source) {
                    casesArray[x][y].setIcon(null);
                    break;
                }
            }
        }
    }
}

一个更安全的解决方案是继续getComponent用作事件源,这可能与事件发生的组件不同......

class MouseClickListener implements MouseListener
{
    public void mouseClicked (MouseEvent event)
    {
        Component source = event.getComponent();
        for (int x = 0; x < casesArray.length; x++) {
            for (int y = 0; y < casesArray[x].length; y++) {
                if (casesArray[x][y] == source) {
                    casesArray[x][y].setIcon(null);
                    break;
                }
            }
        }
    }
}

工作示例

在此处输入图像描述

这基本上从文件夹中加载一堆图像并将它们显示在 6x6 网格中。单击任何图像将其相应标签的图标设置为null

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class ClickTest {

    public static void main(String[] args) {
        new ClickTest();
    }

    public ClickTest() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private JLabel[][] casesArray;

        public TestPane() {

            setLayout(new GridLayout(0, 6));

            File[] files = new File("/path/to/lots/of/images").listFiles();

            MouseListener listener = new MouseAdapter() {
                @Override
                public void mouseClicked(MouseEvent event) {
                    Object source = event.getSource();
                    for (int x = 0; x < casesArray.length; x++) {
                        for (int y = 0; y < casesArray[x].length; y++) {
                            if (casesArray[x][y] == source) {
                                casesArray[x][y].setIcon(null);
                                break;
                            }
                        }
                    }
                }
            };

            casesArray = new JLabel[6][6];
            int index = 0;
            for (int x = 0; x < 6; x++) {
                for (int y = 0; y < 6; y++) {
                    JLabel label = new JLabel();
                    try {
                        label.setIcon(new ImageIcon(ImageIO.read(files[index++])));
                    } catch (IOException ex) {
                        ex.printStackTrace();
                    }
                    label.addMouseListener(listener);
                    casesArray[x][y] = label;
                    add(casesArray[x][y]);
                }
            }
        }
    }
}
于 2013-05-07T01:03:25.093 回答
1

但无论用户点击哪里,只有左上角的图片图标消失

好吧,您正在为每个组件添加一个 MouseListener。因此鼠标点将相对于每个 JLabel。因此,因此只有第一个标签具有准确的鼠标点。

如果您想使用 if/else 逻辑,那么您应该只向包含 36 个标签的父 JPanel 添加一个 MouseListener。然后鼠标点相对于面板,假设您知道每个标签的大小,您可以使用数学来确定面板上特定位置的标签。

更好的解决方案是创建单个侦听器,但将侦听器添加到每个标签。然后您只需使用 MadProgrammer 提到的 getSource() 方法。您的老师应该教您如何使用编写可供多个组件使用的通用侦听器。每当您看到 if/else 逻辑时,您就知道自己的设计很糟糕。

于 2013-05-07T01:18:57.820 回答
0

您可以使用 Netbeans Ide Design 模式生成代码事件并以这种方式复制代码

例如:Jlabel 事件鼠标点击:

  1. 添加鼠标监听器 lboKH.addMouseListener(lb_Mouse_Click_Event);

  2. 声明事件

private MouseListener lb_Mouse_Click_Event = new java.awt.event.MouseAdapter() {

    @Override
    public void mouseClicked(java.awt.event.MouseEvent evt) {
        JOptionPane.showMessageDialog(getRootPane(), "a");
    }
}; 

于 2013-12-25T07:23:11.113 回答