java - Swing JForm 卡住直到操作完成

标签 java swing thread-sleep

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

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()通过按钮的方法,但写 sorter.sort()在 public static void main() 中它可以工作。我该如何修复它?我想我需要将排序放在另一个线程或其他东西上,但我不知道如何。

最佳答案

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

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

了解Concurency in Swing .

关于java - Swing JForm 卡住直到操作完成,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20314894/

相关文章:

java - 组件如何在 JFrame 中并发工作?

安卓 : Retrofit Callback success and failure executed asynchronously?

java - Hibernate-无法从输入流解析映射文档

java - 如何重用与 JavaMail 的连接以避免 AuthenticationFailedException : Too many login attempts?

java - H2 内存DB在MySQL模式下对ORDER BY的处理方式不同

java - Swing 与 Spring 使用注释 besa 映射

java - 在java中将一个jlist中的选定项目显示到另一个jlist中

java - 获取数据在 JTable 中的位置

android - 如何防止我的程序排队按钮按下

java - MySQL 插入 Gson 日期