【问题标题】:Slowing Down Program's execution to show steps减慢程序的执行以显示步骤
【发布时间】:2016-01-10 16:38:33
【问题描述】:

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

【问题讨论】:

  • 你能给我们看一段重绘 JPanel 的代码吗?
  • 标准java中没有延迟功能。你用什么图书馆?向我们展示更多代码,您所描述的原则上可能是好的。然而,很难在代码中发现我们看不到的缺陷
  • 原始包含的代码是用于重绘的全部

标签: java repaint


【解决方案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());

        });
    }
}

【讨论】:

  • 我尝试使用 thread.sleep 但它不起作用,所以我使用了一个每 ___ 秒执行一个步骤的计时器。但是,它不会在等待 ___ 时间后重新绘制。
  • @AntonioK 然后向我们展示更多你的代码,一定有缺陷
  • 该算法通过递归方法工作。每次调用递归方法时,都会执行我包含的代码。延迟有效(我有一个 system.out.println 语句来确保它确实如此。重绘只是没有发生。有什么理由不应该重绘吗?
  • @AntonioK 是的,这是有原因的,正如我所说的那样,您阻塞了 UI 线程。例如,您可以将解决方案的步骤保存在列表中,并在计时器中依次显示。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-01-16
  • 1970-01-01
  • 2015-07-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多