Swing JForm freezes until an action is finished [duplicate]

∥☆過路亽.° 提交于 2019-12-20 06:37:34

问题


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);

    }
}

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.


回答1:


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.

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

Read about Concurency in Swing.



来源:https://stackoverflow.com/questions/20314894/swing-jform-freezes-until-an-action-is-finished

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!