Swing JForm 冻结,直到操作完成 [英] Swing JForm freezes until an action is finished

查看:39
本文介绍了Swing JForm 冻结,直到操作完成的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想创建一个 Java 应用程序,该应用程序使用 Swing 组件可视化合并排序.到目前为止,我已经写了这个:

I want to create a Java application that visualizes merge sort using swing components. So far I've written this:

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextArea;

public class MergeSort extends JFrame {

    private int[] helper;

    private int[] heights;
    private JPanel mainPanel;
    private JTextArea[] areas;
    private JTextArea txtSpeed;
    private JLabel lblSpeed;
    private JButton btnStart;

    private Random rnd;

    private final int FRAME_HEIGHT = 550;
    private final int FRAME_WIDTH = 1100;

    private final int ELEMENTS_TO_SORT = 100;

    private final int BAR_WIDTH = 7;

    private final int SPACING = 10;

    private int SLEEP_TIME = 50;

    public MergeSort() {
        super("Merge Sort Visualisation");
        helper = new int[ELEMENTS_TO_SORT];
        mainPanel = new JPanel();
        mainPanel.setLayout(null);
        rnd = new Random();

        areas = new JTextArea[ELEMENTS_TO_SORT];

        heights = new int[areas.length];

        for (int i = 0; i < areas.length; i++) {
            areas[i] = new JTextArea();
            heights[i] = rnd.nextInt(FRAME_HEIGHT - 100);
            mainPanel.add(areas[i]);
            areas[i].setSize(BAR_WIDTH, heights[i]);

            areas[i].setLocation((i + 1) * SPACING,
                    FRAME_HEIGHT - areas[i].getHeight());
            areas[i].setText(toDigits(heights[i]));
        }

        btnStart = new JButton("Start");
        btnStart.addActionListener(
                new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        try {
                            setSleepTime(Integer.parseInt(txtSpeed.getText()));
                            sort();

                        } catch (NumberFormatException ex) {
                            //s
                        } catch (InterruptedException ex) {
                            //i
                        }

                    }
                }
        );

        mainPanel.add(btnStart);
        btnStart.setSize(100, 25);
        btnStart.setLocation(0, 25);

        txtSpeed = new JTextArea("50");
        mainPanel.add(txtSpeed);
        txtSpeed.setSize(100, 25);
        txtSpeed.setLocation(0, 0);

        lblSpeed = new JLabel("Sleep Time");
        mainPanel.add(lblSpeed);
        lblSpeed.setSize(100, 25);
        lblSpeed.setLocation(110, 0);

        this.add(mainPanel);

        this.setSize(FRAME_WIDTH, FRAME_HEIGHT);

    }

    private void setSleepTime(int x) {
        if (x >= 0) {
            SLEEP_TIME = x;
        } else {
            SLEEP_TIME = 0;
        }
    }

    public void sort() throws InterruptedException {
        mergesort(0, heights.length - 1);
    }

    private void mergesort(int low, int high) throws InterruptedException {

        if (low < high) {

            int middle = low + (high - low) / 2;

            mergesort(low, middle);

            mergesort(middle + 1, high);

            merge(low, middle, high);
        }
    }

    private void merge(int low, int middle, int high) throws InterruptedException {

        for (int i = low; i <= high; i++) {
            helper[i] = heights[i];
        }

        int i = low;
        int j = middle + 1;
        int k = low;

        while (i <= middle && j <= high) {
            if (helper[i] <= helper[j]) {
                heights[k] = helper[i];
                updateAreaX(k);

                Thread.currentThread().sleep(SLEEP_TIME);
                i++;
            } else {
                heights[k] = helper[j];
                updateAreaX(k);

                Thread.currentThread().sleep(SLEEP_TIME);
                j++;
            }
            k++;
        }
        // Copy the rest of the left side of the array into the target array
        while (i <= middle) {
            heights[k] = helper[i];
            updateAreaX(k);

            Thread.currentThread().sleep(SLEEP_TIME);
            k++;
            i++;
        }
    }

    private String toDigits(int a) {
        StringBuilder bdr = new StringBuilder();
        while (a > 0) {
            bdr.insert(0, Integer.toString(a % 10) + String.format("%n"));

            a /= 10;
        }
        if (bdr.length() > 0) {
            bdr.setLength(bdr.length() - 1);
        }

        return bdr.toString();
    }

    private void updateAreaX(int x) {

        areas[x].setSize(BAR_WIDTH, heights[x]);
        areas[x].setLocation(areas[x].getLocation().x,
                FRAME_HEIGHT - areas[x].getHeight() - 40);

        areas[x].setText(toDigits(heights[x]));
    }

    public static void main(String[] args) throws InterruptedException {

        MergeSort sorter = new MergeSort();
        sorter.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        sorter.setVisible(true);

    }
}

问题是,当我单击开始按钮时,整个 JFrame 会冻结,直到所有内容都已排序,然后才显示结果.如果我不通过按钮启动 sort() 方法,而是在 public static void main() 中写入 sorter.sort() 它工作.我该如何解决?我想我需要将排序放在另一个线程或其他东西上,但我不知道如何.

The problem is that when i click the start button the whole JFrame freezes until everything is sorted and then it displays the result. If i don't start the sort() method via the button but write sorter.sort() in the public static void main() it works. How can I fix it? I guess I need to put the sorting on another thread or something but i have no idea how.

推荐答案

您接下来的问题:您在 ActionListener 中阻塞了 EDT,因为您的帧冻结直到 actionPerformed() 方法将被退出.当您使用 Thread.sleep(...) 时,它不会帮助 Swing 重新绘制您的框架.

Your problem in next: you block EDT in your ActionListener, because of your frame freezes until actionPerformed() method will be exited. When you use Thread.sleep(...) it doesn't help Swing to repaint your frame.

似乎您需要使用 Swing Timer 用于更新.您也可以使用 SwingWorker长时间的后台进程.

Seems you need to use Swing Timer for updating. Also you can use SwingWorker for long time background processes.

阅读Swing 中的并发.

这篇关于Swing JForm 冻结,直到操作完成的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆