简体   繁体   English

如何正确使用MouseMotionListener按JButtons?

[英]How to properly use the MouseMotionListener to press JButtons?

I have made a small Conway Game of Life program. 我制作了一个小型的Conway Game of Life计划。 I'm about 80% done. 我完成了大约80%。 I have used a grid of JButtons as the cells. 我使用了一个JButtons网格作为单元格。 Right now I have a ButtonListener on every button so you have to one-by-one draw the pattern you want by clicking on individual buttons. 现在我在每个按钮上都有一个ButtonListener ,所以你必须通过单击各个按钮逐个绘制你想要的模式。 I want to be able to click and drag the mouse and select buttons quickly. 我希望能够单击并拖动鼠标并快速选择按钮。 I used the MotionListener class, implementing the MouseMotionListener and coded the mouseDragged method in an identical fashion as my actionPerformed method in my ButtonListener class. 我使用了MotionListener类,实现了MouseMotionListener并以与ButtonListener类中的actionPerformed方法相同的方式编写了mouseDragged方法。

I thought the logic should be the same but I'm definitely missing something. 我认为逻辑应该是相同的,但我肯定错过了一些东西。 I played around with it a bit, thinking that it was just selecting and de-selecting over and over faster than I could tell. 我玩了一下,认为它只是比我能说的更快地选择和取消选择。 I added a check to make sure that it did not try and change the same button back-to-back but that did not help. 我添加了一个检查,以确保它没有尝试连续更改相同的按钮,但这没有帮助。 Here is my MotionListener class: 这是我的MotionListener类:

    class MotionListener implements MouseMotionListener {

    @Override
    public void mouseDragged(MouseEvent e) {
        for (int i = 0; i < size; i++) {
            for (int j = 0; j < size; j++) {
                if (e.getSource() == squares[i][j]) {
                    if (litSquares[i][j] == false) {
                        squares[i][j].setBackground(selected);
                        litSquares[i][j] = true;
                    } else {
                        squares[i][j].setBackground(backGround);
                        litSquares[i][j] = false;
                    }
                }
            }
        }
    }

    @Override
    public void mouseMoved(MouseEvent e) {
        // TODO Auto-generated method stub

    }

}

My JButton array is squares[][] and the litSquares[][] is a boolean map of what is selected currently, that I use when calculating the next step. 我的JButton阵列是squares[][]litSquares[][]是什么是当前所选的一个布尔地图,我计算下一个步骤时使用。

Any ideas on how to correct my MotionListener ? 关于如何纠正我的MotionListener任何想法? I'm not understanding something about how to properly implement this class. 我不了解如何正确实现这个类。 All simple examples I find deal with drawing, but they all seem to track the Points where the cursor is dragged and update the pixels afterward. 我发现的所有简单示例都涉及绘图,但它们似乎都跟踪拖动光标的Points并在之后更新像素。 Is that something I will have to do somehow with my buttons? 这是我用按钮以某种方式做的事情吗?

***** Here is the MCVE, or at least as small as I could condense it. *****这是MCVE,或者至少可以缩小它。 ***** *****

package extraCredit;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;

import javax.swing.*;
import javax.swing.border.Border;

public class MCVE extends JPanel {

    private static final long serialVersionUID = -8031881678612431401L;

    static JFrame frame;
    static JPanel grid;
    static JButton[][] squares;
    static boolean[][] litSquares, boardCopy;
    static int size, boardSize, tick = 1, goal = 100, rateIncrease = 10;
    ButtonListener listener = new ButtonListener();
    MotionListener mListerner = new MotionListener();
    Border noBorder = BorderFactory.createEmptyBorder();
    Color backGround = Color.BLUE;
    Color selected = Color.PINK;

    public MCVE(int size) {
        MCVE.size = size;
        squares = new JButton[size][size];
        litSquares = new boolean[size][size];
        grid = new JPanel(new GridLayout(size, size));
        for (int i = 0; i < size; i++) {
            for (int j = 0; j < size; j++) {
                squares[i][j] = new JButton();
                squares[i][j].addActionListener(listener);
                // squares[i][j].addMouseMotionListener(mListerner);
                squares[i][j].setBackground(backGround);
                squares[i][j].setBorder(noBorder);
                grid.add(squares[i][j]);
            }
        }

        frame = new JFrame();
        frame.setLayout(new BorderLayout());
        frame.add(grid, BorderLayout.CENTER);
        frame.setTitle("Life");
        if (25 * size < 525) {
            boardSize = 525;
        } else {
            boardSize = 25 * size;
        }
        frame.setSize(boardSize, boardSize);
        frame.setLocationRelativeTo(null);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
    }

    class ButtonListener implements ActionListener {

        @Override
        public void actionPerformed(ActionEvent e) {
            for (int i = 0; i < size; i++) {
                for (int j = 0; j < size; j++) {
                    if (e.getSource() == squares[i][j]) {
                        if (litSquares[i][j] == false) {
                            squares[i][j].setBackground(selected);
                            litSquares[i][j] = true;
                        } else {
                            squares[i][j].setBackground(backGround);
                            litSquares[i][j] = false;
                        }
                    }
                }
            }
        }
    }

    class MotionListener implements MouseMotionListener {

        @Override
        public void mouseDragged(MouseEvent e) {
            for (int i = 0; i < size; i++) {
                for (int j = 0; j < size; j++) {
                    if (e.getSource() == squares[i][j]) {
                        if (litSquares[i][j] == false) {
                            squares[i][j].setBackground(selected);
                            litSquares[i][j] = true;
                        } else {
                            squares[i][j].setBackground(backGround);
                            litSquares[i][j] = false;
                        }
                    }
                }
            }
        }

        @Override
        public void mouseMoved(MouseEvent e) {
            // TODO Auto-generated method stub
        }
    }

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

SOLUTION BELOW , Thanks to @MadProgrammer and @durron597 . 以下解决方案 ,感谢@MadProgrammer和@ durron597。 Mad answered my other question that was hanging me up on this problem. Mad回答了我的另一个问题 ,这个问题让我感到很不舒服。

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.GridLayout;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.util.HashSet;
import java.util.Set;

import javax.swing.*;

public class ChangesAttempt extends JPanel {
private static final long serialVersionUID = -8031881678612431401L;

static JFrame frame;
static JPanel grid;
static JLabel[][] squares;
static boolean[][] litSquares;
static int size, boardSize;
static boolean startDrag, origin;
static Set<Component> compList = new HashSet<Component>();
MouseEvent listener = new MouseEvent();
MotionListener mListerner = new MotionListener();
Color backGround = Color.BLUE;
Color selected = Color.PINK;

public ChangesAttempt(int size) {
    ChangesAttempt.size = size;
    squares = new JLabel[size][size];
    litSquares = new boolean[size][size];
    grid = new JPanel(new GridLayout(size, size));
    grid.addMouseMotionListener(mListerner);
    grid.addMouseListener(listener);
    setBoard();

    frame = new JFrame();
    frame.setLayout(new BorderLayout());
    frame.add(grid, BorderLayout.CENTER);
    frame.setTitle("ChangedLife");
    if (25 * size < 525)
        boardSize = 525;
    else
        boardSize = 25 * size;
    frame.setSize(boardSize, boardSize);
    frame.setLocationRelativeTo(null);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setVisible(true);
}

class MouseEvent implements MouseListener {

    @Override
    public void mousePressed(java.awt.event.MouseEvent e) {
        startDrag = true;
    }

    @Override
    public void mouseClicked(java.awt.event.MouseEvent e) {
        Component source = e.getComponent().getComponentAt(e.getPoint());
        System.out.println("X = " +source.getX() + ", Y = " + source.getY());
        for (int i = 0; i < size; i++) {
            for (int j = 0; j < size; j++) {
                if (source == squares[i][j]) {
                    if (litSquares[i][j] == false) {
                        squares[i][j].setBackground(selected);
                        litSquares[i][j] = true;
                    } else {
                        squares[i][j].setBackground(backGround);
                        litSquares[i][j] = false;
                    }
                }
            }
        }
    }

    @Override
    public void mouseEntered(java.awt.event.MouseEvent e) {
    }

    @Override
    public void mouseExited(java.awt.event.MouseEvent e) {
    }

    @Override
    public void mouseReleased(java.awt.event.MouseEvent e) {
        compList.clear();
    }
}

class MotionListener implements MouseMotionListener {
    @Override
    public void mouseDragged(java.awt.event.MouseEvent e) {
        compList.add(e.getComponent().getComponentAt(e.getPoint()));
        updateBoard();
    }

    @Override
    public void mouseMoved(java.awt.event.MouseEvent e) {

    }
}

public void setBoard() {
    for (int i = 0; i < size; i++) {
        for (int j = 0; j < size; j++) {
            squares[i][j] = new JLabel();
            squares[i][j].setOpaque(true);
            squares[i][j].setBackground(backGround);
            grid.add(squares[i][j]);
        }
    }
}

public void updateBoard(){
    for (int i = 0; i < size; i++) {
        for (int j = 0; j < size; j++) {
            if (compList.contains(squares[i][j])) {
                if(startDrag){
                    startDrag = false;
                    origin = litSquares[i][j];
                }
                if (litSquares[i][j] == origin) {
                    if(origin)
                        squares[i][j].setBackground(backGround);
                    else
                        squares[i][j].setBackground(selected);
                    litSquares[i][j] = !litSquares[i][j];
                }
            }
        }
    }
}

class MyLabel extends JLabel {
    private static final long serialVersionUID = -1414933339546989142L;

}

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

I think the problem you're having is that you're trying to use JButton for something it's not designed to do. 我认为你遇到的问题是你正试图将JButton用于它不能做的事情。 I would go with a much simpler control, like JLabel , so that you won't have all the extra functionality that JButton has. 我会使用更简单的控件,比如JLabel ,这样你就不会拥有JButton具有的所有额外功能。

Secondly, your litSquares array is clearly a Data Clump . 其次,你的litSquares数组显然是一个Data Clump You absolutely should be creating your own custom control (which can either extend JComponent or extend JLabel ), depending on whether JLabel meets your needs, that contains the other information that should be paired with the control itself. 您绝对应该创建自己的自定义控件(可以extend JComponentextend JLabel ),具体取决于JLabel是否满足您的需求,其中包含应与控件本身配对的其他信息。

Thirdly, you might not want the state of the button to be a boolean , you probably want it to be an enum ... like 第三,你可能不希望按钮的状态是一个boolean ,你可能希望它是一个enum ...喜欢

public enum State {
    UNLIT, LIT, CURRENTLY_SELECTED;
}

so that you can see which components are being newly color-flipped. 这样您就可以看到哪些组件正在进行新的颜色翻转。

Finally, as was mentioned in the comments, use public Component getComponentAt(int x, int y) to be able to figure out what the MouseMotionListener was dragged over, and use that to change the color. 最后,正如在注释中提到的那样,使用public Component getComponentAt(int x, int y)能够找出拖动MouseMotionListener ,并使用它来更改颜色。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM