获取鼠标坐标以移动JLabel

时间:2018-06-17 14:38:29

标签: java swing jpanel mouselistener

我正在开发一个项目,开发一款名为的游戏 Don't get mad bro

我有一个JPanel的形状(圆圈)和JLabel组件包含图片。每当我点击&#34时,我都需要它。扔掉骰子" (在后台返回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 个答案:

答案 0 :(得分:1)

  

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

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

  

如何获取mouseClick的坐标?

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

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

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

ColorState

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

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;
    }
}

在for循环中,我们创建JRadioButtons,给它们设置对象状态的ActionListeners,并使用Ellipse2D Shape对象填充Map

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

我们在paintComponent中绘制省略号:

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);
}

最后在MouseAdapter(MouseListener和MouseMotionListener)中,如果单击鼠标左键,我们会监听鼠标按下并注册成功如果单击 ,则形状:

@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
        }
    }
}   

请注意,鼠标拖动代码归功于MadProgrammer的回答here。请将此答案向上投票。

整个班级看起来像这样:

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;
    }
}