【问题标题】:Get mouse coordinates for moving a JLabel获取移动 JLabel 的鼠标坐标
【发布时间】:2018-06-17 14:38:28
【问题描述】:

我正在做一个项目,开发一款名为 Don't get mad bro.

我有一个带有形状(圆圈)的JPanel 和包含图像的JLabel 组件。每当我单击“掷骰子”(在后台返回一个介于 1 和 6 之间的数字)时,我都需要它等待当前玩家点击他的一个棋子,该棋子应该在 n 个位置后移动,其中 n 等于骰子返回的数字。

我的问题是,我应该创建一个新线程来等待mouseClick 事件吗?以及如何获取mouseClick 的坐标?

这是我的类,继承面板并绘制圆圈并添加标签。

public class ImagePanel extends JPanel{

private static final long serialVersionUID = 1L;
ImageMatrix imageMatrix;
BufferedImage[] images;
public static JLabel[][] labels;
DrawGameBoard board = new DrawGameBoard();
List<GameFigure> gameCircles;
List<FinishFigure> finishCircles;
int initialHeight = 528;
int initialWidth = 596;
ThreadForPawnsClick labelsClick;

public ImagePanel(){
    labels = new JLabel[4][4];
    images = new BufferedImage[4];
    setBackground(new Color(255,255,153));
    gameCircles = new ArrayList<GameFigure>();
    finishCircles = new ArrayList<FinishFigure>();
    imageMatrix = new ImageMatrix(initialWidth,initialHeight);

    try {
        images[0] = ImageIO.read(new File("C:\\Users\\babii\\.eclipse\\DontGetMad\\resource\\red.png"));
        images[1] = ImageIO.read(new File("C:\\Users\\babii\\.eclipse\\DontGetMad\\resource\\green.png"));
        images[2] = ImageIO.read(new File("C:\\Users\\babii\\.eclipse\\DontGetMad\\resource\\blue.png"));
        images[3] = ImageIO.read(new File("C:\\Users\\babii\\.eclipse\\DontGetMad\\resource\\yellow.png"));
    } catch (IOException e) {
        e.printStackTrace();
    }
    for(int i=0;i<4;i++)
    {
        for(int j=0;j<4;j++)
        labels[i][j] = new JLabel(new ImageIcon(images[i]));
    }
    setLayout(null);
    board.DrawHomeBoard(imageMatrix, labels);
    for(int i=0;i<4;i++)
        for(int j=0;j<4;j++)
            add(labels[i][j]);
}

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

    int width = this.getWidth();
    int height = this.getHeight();
    imageMatrix.update(width, height);

    setLayout(null);
    gameCircles = board.DrawMainBoard(g, imageMatrix);
    //labels = board.DrawHomeBoard(g, imageMatrix, labels);
    //board.DrawHomeBoard(imageMatrix, labels);
    finishCircles = board.DrawFinishBoard(g, imageMatrix);
    /*for(int i=0;i<4;i++)
        for(int j=0;j<4;j++)
            add(labels[i][j]);
    */
}
}

另外,为什么我的imageMatrix 没有在整个屏幕上扩展,即使我在paintComponent() 中调用更新矩阵?

【问题讨论】:

  • 1) 为了尽快获得更好的帮助,请发帖 minimal reproducible exampleShort, Self Contained, Correct Example。 2) 例如,获取图像的一种方法是热链接到this Q&A 中看到的图像。 3) 应用程序资源在部署时将成为嵌入式资源,因此明智的做法是立即开始访问它们。 embedded-resource 必须通过 URL 而不是文件访问。请参阅info. page for embedded resource 了解如何形成 URL。 ..
  • .. 4) 如果图像加载失败,则将图像添加到标签中。将该循环放在try 中。 5) setLayout(null); 自定义绘画时这不是必需的,并且绘画方法不应该以任何方式更新组件,因为这可能会触发repaint() 6) 请学习常见的Java命名法(命名约定-例如EachWordUpperCaseClassfirstWordLowerCaseMethod()firstWordLowerCaseAttribute,除非它是UPPER_CASE_CONSTANT)并始终如一地使用它。
  • 请查看编辑以回答并询问是否有任何令人困惑的地方。

标签: java swing jpanel mouselistener


【解决方案1】:

我的问题是,我应该创建一个新线程来等待 mouseClick 事件吗?

不,绝对不是。相反,您需要以某种方式将 GUI 的状态更改为等待鼠标单击模式,然后根据其状态更改 GUI 对鼠标单击的响应行为。通常状态由类的实例字段表示。因此,当您需要等待时,您可以更改这些状态​​字段之一,并在单击鼠标时检查该字段的状态并根据该状态改变发生的情况。例如,在回合制国际象棋游戏中,一个状态字段可以是private boolean blackTurn,然后根据鼠标的状态确定鼠标的行为。

以及如何获取鼠标点击的坐标?

在 MouseListener 中,MouseEvent 参数为您提供鼠标相对于被监听组件和屏幕的 x 和 y 位置。如果您的 MouseListener 附加到 JLabel,那么您可以通过 MouseEvent 的 getSource() 方法获取对单击的 JLabel 的引用,然后可以通过调用 getLocation() 获取 JLabel 相对于其容器 JPanel 的位置(如果需要)就可以了。

旁注:在您围绕精灵移动的 Swing GUI 中,通常最好不要将精灵放入 JLabels 中,而是直接在绘图 JPanel 的 paintComponent 方法中绘制它们。


作为我的意思的一个例子,这是一个绘制 4 个彩色圆圈的程序,这些圆圈是可拖动的,但只有在选择相应的 JRadioButton 且 JRadioButton 设置 GUI 的“状态”时才可拖动。这里状态由一个名为ColorState 的枚举表示,它包含4 种颜色和相应的文本。这是这个枚举:

import java.awt.Color;

public enum ColorState {
    RED("Red", Color.RED), 
    GREEN("Green", Color.GREEN), 
    BLUE("Blue", Color.BLUE), 
    ORANGE("Orange", Color.ORANGE);

    private String text;
    private Color color;

    private ColorState(String text, Color color) {
        this.text = text;
        this.color = color;
    }

    public String getText() {
        return text;
    }

    public Color getColor() {
        return color;
    }
}

然后我们创建一个绘图 JPanel,它在 Map 中保存四个 Ellipse2D Shape 对象,

private Map<ColorState, Shape> colorStateMap = new EnumMap<>(ColorState.class);

在 for 循环中,我们创建 JRadioButton,为它们提供设置对象状态的 ActionListener,并使用 Ellipse2D Shape 对象填充地图

for (final ColorState state : ColorState.values()) {
    // create the JRadioButton
    JRadioButton radioButton = new JRadioButton(state.getText());
    add(radioButton); // add to GUI
    buttonGroup.add(radioButton); // add to ButtonGroup

    // give it an ActionListener that changes the object's state
    radioButton.addActionListener(e -> {
        colorState = state;
    });

    // create a randomly placed Ellipse2D and place into Map:
    double x = Math.random() * (W - CIRCLE_WIDTH);
    double y = Math.random() * (H - CIRCLE_WIDTH);
    Ellipse2D ellipse = new Ellipse2D.Double(x, y, CIRCLE_WIDTH, CIRCLE_WIDTH);
    colorStateMap.put(state, ellipse);
}

我们在paintComponent中绘制椭圆:

@Override
protected void paintComponent(Graphics g) {
    super.paintComponent(g);

    // make for smooth graphics
    Graphics2D g2 = (Graphics2D) g;
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

    // iterate through the enum, extracting the ellipse and drawing it
    for (ColorState state : ColorState.values()) {
        Shape shape = colorStateMap.get(state);
        if (shape != null) {
            g2.setColor(state.getColor());
            g2.fill(shape); // draw the ellipse
        }
    }
}   

最后在 MouseAdapter(MouseListener 和 MouseMotionListener)中,我们监听鼠标按下,如果左键被点击如果它被点击适当的范围内,我们就注册成功形状:

private class MyMouse extends MouseAdapter {
    private Shape selectedShape = null;
    private Point2D offset = null;

    @Override
    public void mousePressed(MouseEvent e) {
        // check that correct button pressed
        if (e.getButton() != MouseEvent.BUTTON1) {
            return;
        }

        // has our colorState been set yet? If not, exit
        if (colorState == null) {
            return;
        }

        // is an appropriate Shape held by the Map? If so, get it
        Shape shape = colorStateMap.get(colorState);
        if (shape == null) {
            return;
        }

        // does this shape contain the point where the mouse was pressed?
        if (!shape.contains(e.getPoint())) {
            return;
        }

        // Get the selected shape, get the mouse point location relative to this shape
        selectedShape = shape;
        double x = e.getX() - shape.getBounds2D().getX();
        double y = e.getY() - shape.getBounds2D().getY();
        offset = new Point2D.Double(x, y);
    }

    @Override
    public void mouseDragged(MouseEvent e) {
        // drag shape to new location
        if (selectedShape != null) {
            double x = e.getX() - offset.getX();
            double y = e.getY() - offset.getY();

            Rectangle2D bounds = selectedShape.getBounds2D();
            bounds.setFrame(new Rectangle2D.Double(x, y, bounds.getWidth(), bounds.getHeight()));

            ((Ellipse2D) selectedShape).setFrame(bounds);
            repaint();
        }
    }

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

注意鼠标拖动代码感谢 MadProgrammer 的回答here。请对此答案投票。

整个类是这样的:

import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.util.EnumMap;
import java.util.Map;
import javax.swing.*;

@SuppressWarnings("serial")
public class StateDependentMouseListener extends JPanel {
    private static final int W = 800;
    private static final int H = 650;
    private static final double CIRCLE_WIDTH = 60.0;
    private ButtonGroup buttonGroup = new ButtonGroup();
    private ColorState colorState = null;
    private Map<ColorState, Shape> colorStateMap = new EnumMap<>(ColorState.class);

    public StateDependentMouseListener() {
        setPreferredSize(new Dimension(W, H));
        for (final ColorState state : ColorState.values()) {
            // create the JRadioButton
            JRadioButton radioButton = new JRadioButton(state.getText());
            add(radioButton); // add to GUI
            buttonGroup.add(radioButton); // add to ButtonGroup

            // give it an ActionListener that changes the object's state
            radioButton.addActionListener(e -> {
                colorState = state;
            });

            // create a randomly placed Ellipse2D and place into Map:
            double x = Math.random() * (W - CIRCLE_WIDTH);
            double y = Math.random() * (H - CIRCLE_WIDTH);
            Ellipse2D ellipse = new Ellipse2D.Double(x, y, CIRCLE_WIDTH, CIRCLE_WIDTH);
            colorStateMap.put(state, ellipse);
        }

        MyMouse myMouse = new MyMouse();
        addMouseListener(myMouse);
        addMouseMotionListener(myMouse);
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);

        // make for smooth graphics
        Graphics2D g2 = (Graphics2D) g;
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

        // iterate through the enum, extracting the ellipse and drawing it
        for (ColorState state : ColorState.values()) {
            Shape shape = colorStateMap.get(state);
            if (shape != null) {
                g2.setColor(state.getColor());
                g2.fill(shape); // draw the ellipse
            }
        }
    }   

    private class MyMouse extends MouseAdapter {
        private Shape selectedShape = null;
        private Point2D offset = null;

        @Override
        public void mousePressed(MouseEvent e) {
            // check that correct button pressed
            if (e.getButton() != MouseEvent.BUTTON1) {
                return;
            }

            // has our colorState been set yet? If not, exit
            if (colorState == null) {
                return;
            }

            // is an appropriate Shape held by the Map? If so, get it
            Shape shape = colorStateMap.get(colorState);
            if (shape == null) {
                return;
            }

            // does this shape contain the point where the mouse was pressed?
            if (!shape.contains(e.getPoint())) {
                return;
            }

            // Get the selected shape, get the mouse point location relative to this shape
            selectedShape = shape;
            double x = e.getX() - shape.getBounds2D().getX();
            double y = e.getY() - shape.getBounds2D().getY();
            offset = new Point2D.Double(x, y);
        }

        @Override
        public void mouseDragged(MouseEvent e) {
            // drag shape to new location
            if (selectedShape != null) {
                double x = e.getX() - offset.getX();
                double y = e.getY() - offset.getY();

                Rectangle2D bounds = selectedShape.getBounds2D();
                bounds.setFrame(new Rectangle2D.Double(x, y, bounds.getWidth(), bounds.getHeight()));

                ((Ellipse2D) selectedShape).setFrame(bounds);
                repaint();
            }
        }

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

    private static void createAndShowGui() {
        StateDependentMouseListener mainPanel = new StateDependentMouseListener();

        JFrame frame = new JFrame("StateDependentMouseListener");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(mainPanel);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> createAndShowGui());
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-03
    • 1970-01-01
    • 2011-10-06
    • 2010-09-09
    • 1970-01-01
    相关资源
    最近更新 更多