我有一个运行基本算法来解决谜题的程序。我试图减慢速度,以便用户可以看到算法的运行情况。我希望程序能够显示解决难题所需的步骤。我曾尝试使用计时器甚至thread.sleep来尝试减慢速度。但是,我的GUI(JPanel)在延迟语句之前或之后没有重新绘制。发生的事情是延迟发生并且算法逐步解决,但程序GUI没有更新/重新绘制以显示步骤。以下是该部分的代码:
delay(System.currentTimeMillis(), 500);
repaint();
延迟部分都很好。谁能告诉我为什么JPanel没有重新粉刷?
这是我做的延迟方法:
public static void delay (long a, int x) //Simple Delay Method
{
while((System.currentTimeMillis()-a) < (x/10)){}
}
答案 0 :(得分:1)
你不能只是睡眠UI线程并等待重绘发生,这将停止那段时间的所有用户和操作系统交互(包括重绘事件)。来自repaint documentation:
如果此组件是轻量级组件,则此方法会尽快调用此组件的paint方法。
尽快并不意味着立即,它很可能会安排重新绘制,这将在ui线程被释放时运行。
您必须更改算法以保留其在对象中的状态,并且可以逐步执行,use a timer like in this answer。
示例:
public class SwingMain extends JFrame {
public class MyPanel extends JPanel {
public String state = "Initial";
private JButton btn_start;
public MyPanel() {
super();
btn_start = new JButton("Start");
add(btn_start);
btn_start.addActionListener(e -> doSolve());
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setFont(getFont());
g.drawString(state, 10, 20);
};
@Override
public Dimension getPreferredSize() {
return new Dimension(640, 480);
}
}
private List<String> states;
private int stateIndex;
protected Task token;
private MyPanel pnl_main;
public SwingMain() {
super("Step by step");
setupUi();
}
protected void setupUi() {
pnl_main = new MyPanel();
getContentPane().add(pnl_main);
}
private List<String> modelSolve() {
return Arrays.asList("First", "Second", "Third", "Fourth", "Fifth");
}
public void doSolve() {
this.stateIndex = 0;
this.states = modelSolve();
if (token != null)
token.cancel();
token = GuiTimer.scheduleAtFixedRate(() -> {
if (stateIndex >= states.size()) {
token.cancel();
} else {
pnl_main.state = states.get(stateIndex);
stateIndex++;
pnl_main.repaint();
}
}, 0, 500, TimeUnit.MILLISECONDS);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
SwingMain frame = new SwingMain();
frame.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
System.out.println(frame.pnl_main.getWidth());
System.out.println(frame.pnl_main.getHeight());
});
}
}