编辑:以下最简单,可检查的问题
恢复
我正在做一个Latin Square应用程序,该应用程序设置一个大小为s的正方形,并且您 需要对它进行着色,例如在 同一行或同一列中使用不同的颜色。
但是我的麻烦不是问题本身,而是Swing。
我正在尝试使用Swing来实现某些图形和更好的外观。
问题是,比找到解决方案时,我要停下 来观察几秒钟,然后继续寻找其他对象(我将使用 Thread.sleep()进行此操作)。
但是我正在看广场没有变色。仅当完成 方法时,才会改变自身。
主要问题
在此处输入图片说明
仅显示它找到的最后一个解决方案,并在完成“ 回溯”方法时显示。
当我单击“解析”按钮时,有一个实现 ActionListener接口的类,该接口具有actionPerformed方法,该 方法调用主框架类的方法来解析正方形。因此,问题在于, 如果我在找到解决方案时停止执行,则GUI不会改变, 但是在内部,当我检查属性(调试)时,单元格的颜色 已更新,但在GUI中未更新。
而且我不知道为什么:(
更详细
我的想法是制作一个带有两个面板的框架,一个面板在左侧,一个面板 在中间(也许将来,在面板右侧放一些东西)。
为此,我使用BorderLayout。
因此,左侧的第一个面板类似于基本配置菜单, 用户可以在其中设置正方形的大小并运行该正方形以获得解决方案。
为此,我有两个按钮,一个用于修改大小,另一个用于 解析大小。
所以我需要按钮的事件。尺寸不会给我带来问题,但可以解决 。
因此,我进行了检查,然后检查是否为正方形着色并暂停执行 (Scanner.nextLine()或Thread.sleep())不会在GUI中进行更改,但是 在调试时,属性中的正方形已着色,所以我不太明白 为什么会失败。
我在想什么
所以我有一个按钮,单击该按钮可以解决正方形。而且我认为,我 真的不知道,但是我怀疑这样做会创建一个新的Thread 或其他东西,因此无法更新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); } } } }
好的,首先要注意的是:
Thread.sleep()
setVisible(...)
尝试不要创建自己的线程,而是使用aSwing Timer或a Swing Worker(问题注释中的链接) 因此,考虑到所有这些因素后,我决定创建一个 遵循上述所有规则的新程序,并 在这段时间过后使单元格变蓝3秒钟或变白,并更新JButton 以及禁用防止一次执行多个计时器。
aSwing Timer
Swing Worker
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); }