java - 程序添加太多按钮

标签 java swing awt

我正在尝试制作一个西洋跳棋游戏,到目前为止所有接缝都很好,但是当我将鼠标悬停在按钮上时,图形出现故障,我不知道为什么。它还在顶部添加了很多按钮,当我移动它(调整大小)时它会添加更多。当我按下任何绿色按钮时,它还会添加更多。它们是顶部非常小的按钮,我看不到它们在我的代码中弹出的位置。

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class Test {
 private JButton Green;
 private JButton Blue;

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

public Test() {
    EventQueue.invokeLater(new Runnable() {
        @Override
        public void run() {
            JFrame frame = new JFrame("Checkers");
            JPanel contentPane = new JPanel();


            GameListener listener = new GameListener() {

                @Override
                public void gameWasCompleted() {
                    contentPane.repaint();
                }

                @Override
                public void startNewGame() {
                    System.out.println("button worked");
                    contentPane.repaint();
                }
            };

            MainPane mainPane = new MainPane();
            mainPane.setGameListener(listener);

            contentPane.add(mainPane);

            frame.setContentPane(contentPane);
            frame.pack();
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);
        }
    });
}

public interface GameListener {

    void gameWasCompleted();

    void startNewGame();
}


public class MainPane extends JPanel implements MouseListener {

    private GameListener gameListener;

    public MainPane() {
        addMouseListener(this);
    }

    public void setGameListener(GameListener gameListener) {
        this.gameListener = gameListener;
    }

    @Override
    public Dimension getPreferredSize() {
        return new Dimension(1000, 1000);
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        int xshift;
        int yshift = 0;

        g.setColor(new Color(0, 0, 0));
        for (int i = 0; i < 4; i++) {
            xshift = 125;
            for (int j = 0; j < 4; j++) {
                g.fillRect(xshift, yshift, 125, 125);
                xshift += 250;
            }
            xshift = 0;
            yshift += 125;

            for (int k = 0; k < 4; k++) {
                g.fillRect(xshift, yshift, 125, 125);
                xshift += 250;
            }
            yshift += 125;
        }
        initalprnt(g);
    }


    
    protected void initalprnt(Graphics g) {
        int xshift = 125;
        int yshift = 0;
        g.setColor(new Color(0, 100, 0));
        
        for (int i = 0; i < 3; i++) {
            if (i == 2) {
                xshift = 125;
            }
            for (int j = 0; j < 4; j++) {
                g.fillOval(xshift, yshift, 125, 125);
                Green = new JButton();
                Green.setBackground(new Color(0, 100, 0, 0));
                Green.setBounds(xshift, yshift, 125, 125);
                add(Green);
                

               
                xshift += 250;
            }
            xshift = 0;
            yshift += 125;
        }
        yshift += 250;
        g.setColor(new Color(0, 0, 100));
        for (int k = 0; k < 3; k++) {
            if (k == 2) {
                xshift = 0;
            }
            for (int j = 0; j < 4; j++) {
                g.fillOval(xshift, yshift, 125, 125);
                Blue = new JButton();
                Blue.setBackground(new Color(0, 0, 100, 0));
                Blue.setBounds(xshift, yshift, 125, 125);
                add(Blue);
                xshift += 250;
            }
            xshift = 125;
            yshift += 125;
        }
        buttons();
    }
    
    public void buttons() {
         Green.addActionListener(e -> {
             System.out.println("this does something");
             gameListener.startNewGame();
         });
         Blue.addActionListener(e -> {
             System.out.println("this did something");
             gameListener.startNewGame();
         });
    }

    
    public void mouseClicked(MouseEvent e) {}

    public void mousePressed(MouseEvent e) {}

    public void mouseReleased(MouseEvent e) {}

    public void mouseEntered(MouseEvent e) {}

    public void mouseExited(MouseEvent e) {}
}

}

最佳答案

基本经验法则,在任何情况下都不要在绘制过程中修改组件(或任何其他组件)的状态。这可能(并且可能会)导致组件重新安排另一个绘制 channel ,您将陷入无限循环。

您“可能”实现这一目标的方法有很多,例如,您可以在 GridLayout 中使用 JButton

然后你需要做的就是设计一个合适的模型和委托(delegate)/观察者工作流来保持 UI 与模型同步

Checkers board

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.HashMap;
import java.util.Map;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class Test {

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

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame();
                BoardPane boardPane = new BoardPane();
                boardPane.setBoardListener(new BoardListener() {
                    @Override
                    public void cellWasSelected(Point p) {
                        System.out.println("Cell selected " + p);
                    }
                });
                frame.add(boardPane);
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public interface BoardListener {
        public void cellWasSelected(Point p);
    }

    public class BoardPane extends JPanel {

        private Map<Point, JButton> cells = new HashMap<>();
        private BoardListener boardListener;

        public BoardPane() {
            int gridSize = 8 * 8;
            setLayout(new GridLayout(8, 8));
            int index = 0;
            for (int row = 0; row < 8; row++) {
                int xPos = (row % 2 == 0) ? gridSize : 0;
                for (int col = 0; col < 8; col++) {
                    index++;
                    JButton btn = new JButton();
                    btn.setOpaque(true);
                    btn.setFocusPainted(false);
                    btn.setBorderPainted(false);
                    // I'd prefer to rely on something like
                    // an image, such as an empty image for
                    // cells which are empty
                    btn.setPreferredSize(new Dimension(100, 100));
                    if (index % 2 == 0) {
                        btn.setBackground(Color.BLACK);
                        btn.setForeground(Color.WHITE);
                    } else {
                        btn.setBackground(Color.WHITE);
                        btn.setForeground(Color.BLACK);
                    }
                    Point p = new Point(col, row);
                    btn.putClientProperty("cell", p);
                    cells.put(p, btn);
                    add(btn);

                    btn.addActionListener(new ActionListener() {
                        @Override
                        public void actionPerformed(ActionEvent e) {
                            BoardListener listener = getBoardListener();
                            if (listener == null) {
                                return;
                            }
                            Point p = (Point)btn.getClientProperty("cell");
                            listener.cellWasSelected(p);
                        }
                    });
                }
                index++;
            }
        }

        public void setBoardListener(BoardListener boardListener) {
            this.boardListener = boardListener;
        }

        public BoardListener getBoardListener() {
            return boardListener;
        }

    }
}

通常,我会使用完全基于组件或基于自定义绘画的解决方案,并避免将两者混用。

请记住,董事会应该只关注董事会需要做的事情,而不应该做任何其他事情。这就是“关注/责任分离”的要点

一个复杂得多的解决方案可能会使用自定义布局来管理自定义绘制(paint)板上的组件,但这远远超出了问题的范围或您此时的能力

关于java - 程序添加太多按钮,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69322273/

相关文章:

Java 设计 : Enum state?

java - 如何使用 SwingUtilities.invokeLater 调用阻塞模式

java - 如何在JTree中添加windows目录结构?

java - 我无法修改我的 boolean 字段?

java - 无法在 Java 中关闭框架?

java - 正确使用 toString 打印数组?

java - JavaFX TableView 中的重复列

java - 什么是NullPointerException,我该如何解决?

Java:按住鼠标时基于二维数组填充图形

java - 我应该在我的应用程序中声明 swing 组件为最终的吗?