Java Swing:GUI未更新某些属性
编辑:下面是一个最简单、可检查的问题 继续 我正在做一个拉丁方应用程序,它设置了一个大小为s的正方形,你需要给它上色,有一些限制,比如,同一行或同一列中的颜色不同 但我的问题不是问题本身,而是摇摆 我正在尝试用Swing来制作一些图形和更好的外观 问题是,当我找到一个解决方案时,我想停下来看几秒钟,然后继续寻找其他解决方案(我将使用Thread.sleep()来完成) 但我注意到广场没有变红。只有在完成该方法后,才会更改自身 主要问题 仅显示它找到的最后一个解决方案,并显示何时完成回溯方法 当我单击resolve按钮时,有一个类实现了ActionListener接口,该接口具有actionPerformed方法,该方法调用主框架类的一个方法,该方法解析正方形。所以问题是,如果在找到解决方案时停止执行,GUI不会改变, 但是在内部,当我检查属性(调试)时,单元格的颜色已经更新,但没有在GUI中更新 我不知道为什么:( 更详细 我的想法是,制作一个有两个窗格的框架,一个在左边,一个在中间(也许将来,在右边放一些东西) 为此,我使用了边界布局 因此,左边的第一个窗格类似于基本配置菜单,用户可以在其中设置正方形的大小并运行它以获得解决方案 为此,我有两个按钮,一个用于修改大小,另一个用于解决它 所以我需要按钮的事件。大小不是给我带来问题,而是解决问题 所以我签出了,如果我给一些方块上色并暂停执行(Scanner.nextLine()或Thread.sleep())在GUI中没有进行更改,但是当我调试时,方块在属性中上色了,所以我不太明白为什么会出错 我认为问题出在哪里 所以我有一个按钮,它在点击时解析正方形。 我想,我真的不知道,但我怀疑,这样做会创建一个新线程或其他东西,因此,无法更新GUI;只有在完成后,才能更新 无论如何都有办法改变这个Java Swing:GUI未更新某些属性,java,swing,user-interface,Java,Swing,User Interface,编辑:下面是一个最简单、可检查的问题 继续 我正在做一个拉丁方应用程序,它设置了一个大小为s的正方形,你需要给它上色,有一些限制,比如,同一行或同一列中的颜色不同 但我的问题不是问题本身,而是摇摆 我正在尝试用Swing来制作一些图形和更好的外观 问题是,当我找到一个解决方案时,我想停下来看几秒钟,然后继续寻找其他解决方案(我将使用Thread.sleep()来完成) 但我注意到广场没有变红。只有在完成该方法后,才会更改自身 主要问题 仅显示它找到的最后一个解决方案,并显示何时完成回溯方法
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;
进口