Java Swing: GUI is not updating some properties

前端 未结 2 2025
我寻月下人不归
我寻月下人不归 2021-01-22 18:52

EDIT: A EASIEST, SIMPLE AND CHECKABLE PROBLEM BELOW

RESUME

I\'m doing a Latin Square application, which, sets a square of size

2条回答
  •  盖世英雄少女心
    2021-01-22 19:26

    Ok, first things first:

    1. Don't update your GUI using Thread.sleep() it will block the EDT
    2. You're not placing your program on the EDT, see point number 2 in this answer
    3. Don't extend JFrame, instead create an instance of it, see: Extends JFrame vs. creating it inside the program
    4. Don't make your program visible (i.e. call setVisible(...)) before adding all the components to it. It may cause your program to behave in a wrong manner.
    5. Try not creating your own threads, instead use a Swing Timer or a Swing Worker (links in the question's comments)

    So, taking all of that into consideration, I decided to create a new program that follows all the above rules and makes the cells blue for 3 seconds or white after that time has passed, and also updates the text in the JButton as well as disabling to prevent multiple timers executing at once.

    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.GridLayout;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    
    import javax.swing.BoxLayout;
    import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.SwingUtilities;
    import javax.swing.Timer;
    
    public class Test {
        private JFrame frame;
        private JPanel pane;
        private JPanel cellsPane;
        private MyCell[][] cells;
        private JButton button;
        private Timer timer;
    
        private int counter = 3;
        private boolean isFinished = false;
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(() -> new Test().createAndShowGui());
        }
    
        private void createAndShowGui() {
            frame = new JFrame(getClass().getSimpleName());
    
            pane = new JPanel();
            cellsPane = new JPanel();
    
            pane.setLayout(new BoxLayout(pane, BoxLayout.PAGE_AXIS));
            cellsPane.setLayout(new GridLayout(4, 4, 5, 5));
    
            cells = new MyCell[4][4];
    
            for (int i = 0; i < cells.length; i++) {
                for (int j = 0; j < cells[i].length; j++) {
                    cells[i][j] = new MyCell(Color.WHITE);
                    cellsPane.add(cells[i][j]);
                }
            }
    
            button = new JButton("Press me!");
            timer = new Timer(1000, listener);
    
            button.addActionListener(e -> {
                button.setEnabled(false);
                isFinished = false;
                updateCellsColors();
                timer.start();
            });
    
            pane.add(cellsPane);
            pane.add(button);
    
            frame.add(pane);
            frame.pack();
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setVisible(true);
        }
    
        private void updateCellsColors() {
            for (int i = 0; i < cells.length; i++) {
                for (int j = 0; j < cells[i].length; j++) {
                    cells[i][j].setCellColor(isFinished ? Color.WHITE : Color.BLUE);
                }
            }
        }
    
        private ActionListener listener = new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (counter == 0) {
                    timer.stop();
                    counter = 3;
                    isFinished = true;
                    button.setEnabled(true);
                    updateCellsColors();
                }
                if (isFinished) {
                    button.setText("Press me!");
                } else {
                    button.setText("You have " + counter + " seconds remaining");
                }
                counter--;
            }
        };
    }
    
    @SuppressWarnings("serial")
    class MyCell extends JPanel {
        private Color cellColor;
    
        public Color getCellColor() {
            return cellColor;
        }
    
        public void setCellColor(Color cellColor) {
            this.cellColor = cellColor;
            this.setBackground(cellColor);
        }
    
        public MyCell(Color cellColor) {
            this.cellColor = cellColor;
            this.setOpaque(true);
            this.setBackground(cellColor);
        }
    
        @Override
        public Dimension getPreferredSize() {
            // TODO Auto-generated method stub
            return new Dimension(30, 30);
        }
    }
    

    You can copy-paste it and see the same result as me:

提交回复
热议问题