Java Swing:GUI未更新某些属性

Java Swing:GUI未更新某些属性,java,swing,user-interface,Java,Swing,User Interface,编辑:下面是一个最简单、可检查的问题 继续 我正在做一个拉丁方应用程序,它设置了一个大小为s的正方形,你需要给它上色,有一些限制,比如,同一行或同一列中的颜色不同 但我的问题不是问题本身,而是摇摆 我正在尝试用Swing来制作一些图形和更好的外观 问题是,当我找到一个解决方案时,我想停下来看几秒钟,然后继续寻找其他解决方案(我将使用Thread.sleep()来完成) 但我注意到广场没有变红。只有在完成该方法后,才会更改自身 主要问题 仅显示它找到的最后一个解决方案,并显示何时完成回溯方法

编辑:下面是一个最简单、可检查的问题

继续

我正在做一个拉丁方应用程序,它设置了一个大小为s的正方形,你需要给它上色,有一些限制,比如,同一行或同一列中的颜色不同

但我的问题不是问题本身,而是摇摆

我正在尝试用Swing来制作一些图形和更好的外观

问题是,当我找到一个解决方案时,我想停下来看几秒钟,然后继续寻找其他解决方案(我将使用Thread.sleep()来完成)

但我注意到广场没有变红。只有在完成该方法后,才会更改自身

主要问题

仅显示它找到的最后一个解决方案,并显示何时完成回溯方法

当我单击resolve按钮时,有一个类实现了ActionListener接口,该接口具有actionPerformed方法,该方法调用主框架类的一个方法,该方法解析正方形。所以问题是,如果在找到解决方案时停止执行,GUI不会改变, 但是在内部,当我检查属性(调试)时,单元格的颜色已经更新,但没有在GUI中更新

我不知道为什么:(

更详细

我的想法是,制作一个有两个窗格的框架,一个在左边,一个在中间(也许将来,在右边放一些东西)

为此,我使用了边界布局

因此,左边的第一个窗格类似于基本配置菜单,用户可以在其中设置正方形的大小并运行它以获得解决方案

为此,我有两个按钮,一个用于修改大小,另一个用于解决它

所以我需要按钮的事件。大小不是给我带来问题,而是解决问题

所以我签出了,如果我给一些方块上色并暂停执行(Scanner.nextLine()或Thread.sleep())在GUI中没有进行更改,但是当我调试时,方块在属性中上色了,所以我不太明白为什么会出错

我认为问题出在哪里

所以我有一个按钮,它在点击时解析正方形。 我想,我真的不知道,但我怀疑,这样做会创建一个新线程或其他东西,因此,无法更新GUI;只有在完成后,才能更新

无论如何都有办法改变这个

class ResolveListener implements  ActionListener
        {
            @Override
            public void actionPerformed(ActionEvent e)
            {
                int size = Integer.parseInt(textField.getText());
                latinSquareFrame.resolve(size);
            }
        }

一个简单的问题

我在评论中读到了搜索类似于此的最小且易于检查的问题

这个代码和我的问题相似,有一个正方形,我和我想在点击按钮时给它上色

问题是,如果我暂停它,它不是彩色的,只有在方法完成时才是彩色的,我不知道为什么

我想这和我以前遇到的问题很相似

这是我能用来解决这个问题的最低限度的代码

    package LatinSquare;


import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Scanner;

public class Test
{
    public static void main(String[] args)
    {
        TestFrame testFrame = new TestFrame();
    }
}

class TestFrame extends JFrame
{

    public TestFrame()
    {
        this.setVisible(true);
        this.setBounds(400,300,400,300);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setLayout(new BorderLayout());
        TestJPanel testJPanel = new TestJPanel();
        this.add(testJPanel,BorderLayout.CENTER);

        TestContainerButtonJPanel testContainerButtonJPanel = new TestContainerButtonJPanel(testJPanel);
        this.add(testContainerButtonJPanel, BorderLayout.SOUTH);

        this.revalidate();
        this.repaint();
    }

}

class TestContainerButtonJPanel extends JPanel
{
    private JButton resolve;
    public TestJPanel testJPanel;

    public TestContainerButtonJPanel(TestJPanel testJPanel)
    {
        this.testJPanel = testJPanel;
        this.setVisible(true);
        resolve = new JButton("RESOLVE");
        ActionListener resolveListener = new ResolveListener();
        resolve.addActionListener(resolveListener);
        this.add(resolve);

    }

    class ResolveListener implements ActionListener
    {
        @Override
        public void actionPerformed(ActionEvent e)
        {
            try {
                TestContainerButtonJPanel.this.testJPanel.colourCells();
            } catch (InterruptedException e1) {
                e1.printStackTrace();
            }
        }


    }
}


class TestJPanel extends JPanel
{
    private JButton[][] board;
    public TestJPanel()
    {
        this.board = new JButton[4][4];
        this.setVisible(true);
        this.setLayout(new GridLayout(4,4));
        for(int i=0; i<4;i++)
        {
            for(int j=0; j<4;j++)
            {
                JButton cell = new JButton();
                board[i][j] = cell;
                board[i][j].setBackground(Color.WHITE);
                this.add(cell);
            }
        }

    }

    public void colourCells() throws InterruptedException {
        for(int i=0; i<4;i++)
        {
            for(int j=0;j<4;j++)
            {
                this.board[i][j].setBackground(Color.RED);
                Thread.sleep(300);

            }
        }

    }


}
package;
导入javax.swing.*;
导入java.awt.*;
导入java.awt.event.ActionEvent;
导入java.awt.event.ActionListener;
导入java.util.Scanner;
公开课考试
{
公共静态void main(字符串[]args)
{
TestFrame TestFrame=新的TestFrame();
}
}
类TestFrame扩展了JFrame
{
公共测试框架()
{
此.setVisible(true);
此.立根(400300400300);
此.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
此.setLayout(新的BorderLayout());
TestJPanel TestJPanel=新的TestJPanel();
add(testJPanel,BorderLayout.CENTER);
TestContainerButtonJPanel TestContainerButtonJPanel=新的TestContainerButtonJPanel(testJPanel);
add(testContainerButtonJPanel,BorderLayout.SOUTH);
这个。重新验证();
这个。重新绘制();
}
}
类TestContainerButtonJPanel扩展了JPanel
{
私有按钮解析;
公共TestJPanel TestJPanel;
公共TestContainerButtonJPanel(TestJPanel TestJPanel)
{
this.testJPanel=testJPanel;
此.setVisible(true);
resolve=新按钮(“resolve”);
ActionListener resolveListener=新的resolveListener();
addActionListener(resolveListener);
本条增补(决议);
}
类ResolveListener实现ActionListener
{
@凌驾
已执行的公共无效操作(操作事件e)
{
试一试{
TestContainerButtonJPanel.this.testJPanel.colorCells();
}捕捉(中断异常e1){
e1.printStackTrace();
}
}
}
}
类TestJPanel扩展了JPanel
{
私有JButton[]]板;
公共测试面板()
{
this.board=新的JButton[4][4];
此.setVisible(true);
这个.setLayout(新的GridLayout(4,4));

对于(inti=0;i需要另一个线程来修复它

更改侦听器类,效果良好:

 class ResolveListener implements ActionListener
    {
        @Override
        public void actionPerformed(ActionEvent e)
        {
            new Thread(new Runnable()
            {
                @Override
                public void run()
                {
                    try {
                        TestContainerButtonJPanel.this.testJPanel.colourCells();
                    } catch (InterruptedException e1) {
                        e1.printStackTrace();
                    }
                }
            }).start();
        }


    }
}

好的,首先要做的是:

  • 不要使用
    Thread.sleep()
    更新GUI,它会阻止EDT
  • 您没有将程序放在EDT上,请参见中的第2点
  • 不要扩展JFrame,而是创建它的实例,请参见:
  • 在添加所有组件之前,不要使程序可见(即调用
    setVisible(…)
    ),这可能会导致程序以错误的方式运行
  • 试着不要创建自己的线程,而是使用
    摆动计时器
    摆动工作线程
    (问题注释中的链接)
  • 因此,考虑到所有这些因素,我决定创建一个新程序,该程序遵循上述所有规则,并在时间过去后使单元格变蓝3秒或变白,同时更新
    JButton
    中的文本,并禁用以防止多个计时器同时执行

    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);
        }
    }
    
    导入java.awt.Color;
    导入java.awt.Dimension;
    进口