减慢程序的执行以显示步骤

时间:2016-01-10 16:38:33

标签: java repaint

我有一个运行基本算法来解决谜题的程序。我试图减慢速度,以便用户可以看到算法的运行情况。我希望程序能够显示解决难题所需的步骤。我曾尝试使用计时器甚至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)){}
}

1 个答案:

答案 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());

        });
    }
}