代码之家  ›  专栏  ›  技术社区  ›  Luis de la Cal

重置按钮数组后无法更改java按钮颜色

  •  2
  • Luis de la Cal  · 技术社区  · 7 年前

    我正在创建一个程序,在这个程序中,我必须不时重置一个按钮数组并将其显示在jPanel上。下面的函数将jButton添加到我的面板中,并在第一次调用它时完美地显示它们,但从那时起,每次我调用它(清空jButton数组并将.removeAll()应用到面板后),它都不允许我更改jButton的背景色。一些帮助来帮助我找出这将是伟大的,谢谢。

    import java.awt.*;
    import java.awt.Font;
    import java.awt.GridLayout;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.awt.event.MouseEvent;
    import java.awt.event.MouseListener;
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.ArrayList;
    import java.util.Collections;
    import javafx.scene.layout.Border;
    import javax.swing.*;
    
    /**
     *
     * @author Luis
     */
    public class MineSweeper extends JFrame implements ActionListener {
    
        int int_dim = 11;
        int int_cellsShown = 0;
        JButton[][] arr_btnField = new JButton[int_dim][int_dim];
        int[][] arr_solution = new int[int_dim][int_dim];
        Color[] clr_palette = {Color.white, new Color(0X00, 0X94, 0XFF), new Color(0X00, 0X26, 0XFF), new Color(0X00, 0XAA, 0X0A), Color.red, Color.MAGENTA, new Color(0XFF, 0X00, 0X00), new Color(0X9B, 0X00, 0X00)};
        boolean bool_change = false;
        boolean bool_won = false;
        boolean bool_firstround = false;
    
    javax.swing.border.Border border = BorderFactory.createLineBorder(Color.darkGray, 1, true);
    
    MenuBar menu_bar;
    Menu menu;
    MenuItem optionNew;
    //boolean[][] arr_boolShowed=new boolean[int_dim][int_dim];
    int int_mines = 8;
    ArrayList<Integer> arl_field = new ArrayList<Integer>();
    JPanel jpanel = new JPanel();
    JPanel jpanel2 = new JPanel();
    
    //ArrayList<Boolean> arl_boolShowed = new ArrayList<Boolean>();
    /**
     * @param args the command line arguments
     */
    public MineSweeper() throws FontFormatException, IOException {
    
        resetGame();
    
        //JFrame frame = new JFrame("");
        this.getContentPane().add(jpanel);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setResizable(true);
        this.setTitle("Minesweeper");
        this.pack();
        this.setLocationRelativeTo(null);
        this.setVisible(true);
        this.setSize(500, 500);
    
        menu_bar = new MenuBar();
        menu = new Menu("File");
        optionNew = new MenuItem("Win");
        optionNew.addActionListener(this);
        menu.add(optionNew);
        menu_bar.add(menu);
        this.setMenuBar(menu_bar);
    }
    
    public void resetGame() {
        jpanel.removeAll();
        arl_field.clear();
    
        arr_btnField = new JButton[int_dim][int_dim];
        arr_solution = new int[int_dim][int_dim];
        bool_change = false;
        bool_won = false;
        //arl_field = new ArrayList<Integer>();
    
        for (int i = 0; i < arr_solution.length; i++) {
            for (int j = 0; j < arr_solution[i].length; j++) {
                arr_solution[i][j] = 1;
            }
        }
    
        jpanel.setLayout(new GridLayout(0, int_dim));//if(bool_firstround==false)jpanel.setLayout(new GridLayout(0,int_dim));
    
        for (int i = 0; i < arr_btnField.length; i++) {
            for (int j = 0; j < arr_btnField[i].length; j++) {
                arr_btnField[i][j] = new JButton();////if(bool_firstround==false)arr_btnField[i][j] = new JButton();//arl_field.get(i*int_dim+j)+"");
                arr_btnField[i][j].setText("");
                arr_btnField[i][j].setBackground(new Color(0X00, 0X94, 0XFF));
                arr_btnField[i][j].setBorder(border);
                arr_btnField[i][j].setForeground(clr_palette[1]);
                arr_btnField[i][j].addMouseListener(listener);
                arr_btnField[i][j].setFocusable(false);
                jpanel.add(arr_btnField[i][j]);
            }
        }
    
        jpanel.revalidate();
        jpanel.repaint();
    }
    
    public static void main(String[] args) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    new MineSweeper();
                    UIManager.setLookAndFeel(
                            UIManager.getSystemLookAndFeelClassName());
                } catch (Exception ex) {
                }
            }
        });
    }
    
    MouseListener listener = new MouseListener() {
        @Override
        public void mouseClicked(MouseEvent e) {
    
        }
    
        @Override
        public void mousePressed(MouseEvent e) {
            outerloop:
            for (int i = 0; i < arr_btnField.length; i++) {
                for (int j = 0; j < arr_btnField[i].length; j++) {
                    if (e.getSource() == arr_btnField[i][j]) {
                        if (SwingUtilities.isLeftMouseButton(e)) {
                            labelText(i, j);
                        }
                        if (SwingUtilities.isRightMouseButton(e)) {
                            arr_btnField[i][j].setBackground(Color.red);
                        }
                        //bool_won=false;
                        break outerloop;
                    }
                }
            }
        }
    
        @Override
        public void mouseReleased(MouseEvent e) {
        }
    
        @Override
        public void mouseEntered(MouseEvent e) {
            if (bool_won == true)
                gameWon();
        }
    
        @Override
        public void mouseExited(MouseEvent e) {
        }
    
    };
    
    public void labelText(int i, int j) {
        if (bool_won == false) {
            arr_btnField[i][j].setText("1");
            arr_btnField[i][j].setBackground(Color.white);
            if (arr_btnField[i][j].getBorder() == border) {
                int_cellsShown++;
                System.out.println("Cells shown: " + int_cellsShown);
                if (int_cellsShown >= (int_dim * int_dim - int_mines)) {
                    bool_won = true;
                }
            }
            if (bool_won == false)
                arr_btnField[i][j].setBorder(BorderFactory.createLineBorder(Color.darkGray, 1, true));
        }
    }
    
    public void gameWon() {
        int dialogResult = JOptionPane.showConfirmDialog(null, "You Won! Do you want to start a new game?", "Congratulations!", JOptionPane.YES_NO_OPTION);
        if (dialogResult == JOptionPane.YES_OPTION) {
            bool_won = false;
            int_cellsShown = 0;
            resetGame();
        }
    }
    
    @Override
    public void actionPerformed(ActionEvent e) {
        int_cellsShown = 0;
        int_dim++;
        resetGame();
    
    
         for (int i = 0; i < arr_btnField.length; i++) {
                for (int j = 0; j < arr_btnField[i].length; j++) {
                    arr_btnField[i][j].setBackground(Color.red);
                }
            }
        }
    }
    

    第一次后显示:
    Display after the first time

    第二次后显示:
    Display after the second time

    2 回复  |  直到 7 年前
        1
  •  2
  •   camickr    7 年前

    我调用。在方法的第四行重新验证。

    这没有任何作用,因为没有向面板添加任何组件。需要在添加组件后执行重新验证()。

    显示的面板不是jpanel,显示的面板是jpanel2,这就是为什么我在方法末尾将jpanel2指定给jpanel的值。

    您不能仅仅更改一个参照,然后期望组件从一个面板移动到另一个面板。

    组件需要添加到添加到GUI的面板中。

    编辑:

    首先,回转组件以“J”开头。不要在Swing应用程序中使用AWT组件(菜单栏、菜单、菜单项)。

    问题是您的LAF:

    new MineSweeper();
    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
    

    组件是使用当前LAF创建的。首次创建游戏时,默认LAF用于创建所有按钮(和其他组件)。此LAF允许您更改按钮的背景色。

    但是,然后更改LAF。因此,当您重置游戏板时,按钮现在使用系统LAF创建。这个LAF显然不允许您更改按钮的背景色。

    这应该很容易测试。创建GUI:

    //UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
    
    JButton button = new JButton("testing");
    button.setBackground(Color.RED);
    
    JFrame frame = new JFrame("SSCCE");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.add( button );
    frame.pack();
    frame.setLocationByPlatform( true );
    frame.setVisible( true );
    

    首先按照上面的步骤测试代码,看看按钮的背景是否发生了变化。

    然后取消LAF更改的注释并重新测试。

    一种不依赖LAF的可能解决方案是使用图标来表示按钮的背景色。然后,您可以将任何文本居中放置在图标顶部。类似于:

    import java.awt.*;
    import javax.swing.*;
    
    public class ColorIcon implements Icon
    {
        private Color color;
        private int width;
        private int height;
    
        public ColorIcon(Color color, int width, int height)
        {
            this.color = color;
            this.width = width;
            this.height = height;
        }
    
        public int getIconWidth()
        {
            return width;
        }
    
        public int getIconHeight()
        {
            return height;
        }
    
        public void paintIcon(Component c, Graphics g, int x, int y)
        {
            g.setColor(color);
            g.fillRect(x, y, width, height);
        }
    
        public static void main(String[] args)
        {
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    createAndShowGUI();
                }
            });
        }
    
        public static void createAndShowGUI()
        {
            JPanel panel = new JPanel( new GridLayout(2, 2) );
    
            for (int i = 0; i < 4; i++)
            {
                Icon icon = new ColorIcon(Color.RED, 50, 50);
                JLabel label = new JLabel( icon );
                label.setText("" + i);
                label.setHorizontalTextPosition(JLabel.CENTER);
                label.setVerticalTextPosition(JLabel.CENTER);
                panel.add(label);
            }
    
            JFrame f = new JFrame();
            f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            f.getContentPane().add(panel);
            f.setSize(200, 200);
            f.setLocationRelativeTo( null );
            f.setVisible(true);
        }
    }
    
        2
  •  1
  •   Hovercraft Full Of Eels    7 年前

    是的,我也刚刚注意到,问题就在这里:

    public static void main(String[] args) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    new MineSweeper();
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (Exception ex) {
                }
            }
        });
    }
    

    如果注释掉UIManager行,则代码可以正常工作。此行仅有效 之后 GUI已经创建,因此在创建新组件之前不会生效。请注意,我正在努力最小化您的代码以发现这一点,并正在裁剪代码以查看问题的原因,直到剩下的就这些了。

    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.GridLayout;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.awt.event.KeyEvent;
    
    import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.JMenu;
    import javax.swing.JMenuBar;
    import javax.swing.JMenuItem;
    import javax.swing.JPanel;
    import javax.swing.UIManager;
    
    @SuppressWarnings("serial")
    public class MineSweeper extends JFrame implements ActionListener {
        private static final Color BTN_COLOR = new Color(0X00, 0X94, 0XFF);
        int int_dim = 11;
        JButton[][] arr_btnField = new JButton[int_dim][int_dim];
    
        JMenuBar menu_bar;
        JMenu menu;
        JMenuItem optionNew;
        JPanel jpanel = new JPanel();
    
        public MineSweeper() {
            resetGame();
            this.getContentPane().add(jpanel);
            this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            this.setResizable(true);
            this.setTitle("Minesweeper");
    
            menu_bar = new JMenuBar();
            menu = new JMenu("File");
            menu.setMnemonic(KeyEvent.VK_F);
    
            optionNew = new JMenuItem("Win");
            optionNew.setMnemonic(KeyEvent.VK_W);
            optionNew.addActionListener(this);
            menu.add(optionNew);
            menu_bar.add(menu);
            this.setJMenuBar(menu_bar);
            this.setPreferredSize(new Dimension(500, 500));
            this.pack();
            this.setLocationRelativeTo(null);
            this.setVisible(true);
        }
    
        public void resetGame() {
            jpanel.removeAll();
            arr_btnField = new JButton[int_dim][int_dim];
            jpanel.setLayout(new GridLayout(0, int_dim));
            for (int i = 0; i < arr_btnField.length; i++) {
                for (int j = 0; j < arr_btnField[i].length; j++) {
                    arr_btnField[i][j] = new JButton();
                    arr_btnField[i][j].setBackground(BTN_COLOR);
                    jpanel.add(arr_btnField[i][j]);
                }
            }
            jpanel.revalidate();
            jpanel.repaint();
        }
    
        @Override
        public void actionPerformed(ActionEvent e) {
            resetGame();
        }
    
        public static void main(String[] args) {
            java.awt.EventQueue.invokeLater(new Runnable() {
                public void run() {
                    try {
                        new MineSweeper();
                        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                    } catch (Exception ex) {
                    }
                }
            });
        }
    
    }