[英]How to properly use the MouseMotionListener to press JButtons?
我制作了一個小型的Conway Game of Life計划。 我完成了大約80%。 我使用了一個JButtons
網格作為單元格。 現在我在每個按鈕上都有一個ButtonListener
,所以你必須通過單擊各個按鈕逐個繪制你想要的模式。 我希望能夠單擊並拖動鼠標並快速選擇按鈕。 我使用了MotionListener
類,實現了MouseMotionListener
並以與ButtonListener
類中的actionPerformed
方法相同的方式編寫了mouseDragged
方法。
我認為邏輯應該是相同的,但我肯定錯過了一些東西。 我玩了一下,認為它只是比我能說的更快地選擇和取消選擇。 我添加了一個檢查,以確保它沒有嘗試連續更改相同的按鈕,但這沒有幫助。 這是我的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
}
}
我的JButton陣列是squares[][]
和litSquares[][]
是什么是當前所選的一個布爾地圖,我計算下一個步驟時使用。
關於如何糾正我的MotionListener
任何想法? 我不了解如何正確實現這個類。 我發現的所有簡單示例都涉及繪圖,但它們似乎都跟蹤拖動光標的Points
並在之后更新像素。 這是我用按鈕以某種方式做的事情嗎?
*****這是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);
}
}
以下解決方案 ,感謝@MadProgrammer和@ durron597。 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);
}
}
我認為你遇到的問題是你正試圖將JButton
用於它不能做的事情。 我會使用更簡單的控件,比如JLabel
,這樣你就不會擁有JButton
具有的所有額外功能。
其次,你的litSquares
數組顯然是一個Data Clump 。 您絕對應該創建自己的自定義控件(可以extend JComponent
或extend JLabel
),具體取決於JLabel
是否滿足您的需求,其中包含應與控件本身配對的其他信息。
第三,你可能不希望按鈕的狀態是一個boolean
,你可能希望它是一個enum
...喜歡
public enum State {
UNLIT, LIT, CURRENTLY_SELECTED;
}
這樣您就可以看到哪些組件正在進行新的顏色翻轉。
最后,正如在注釋中提到的那樣,使用public Component getComponentAt(int x, int y)
能夠找出拖動MouseMotionListener
,並使用它來更改顏色。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.