Java swing repainting while computing: animating sorting algorithm

前端 未结 1 782
隐瞒了意图╮
隐瞒了意图╮ 2020-12-12 07:13

http://www.youtube.com/watch?v=M0cNsmjK33E

I want to develop something similar to the link above using Java Swing. I have the sorting method and did while repaint bu

相关标签:
1条回答
  • 2020-12-12 07:46

    Note: I started writing this before the question was deleted

    Most likely your using some looping mechanism and praying that each iteration, the ui with be updated. That's a wrong assumption. The UI will not be update until the loop is finished. What you are doing is what we refer to as blocking the Event Dispatch Thread(EDT)

    See How to use a Swing Timer. Make "iterative" updates in the ActionListener call back. For instance, if you want to animate a sorting algorithm, you need to determine what needs to be updated per "iteration" of the timer callback. Then each iteration repaint the ui.

    So your Timer timer could look something like

    Timer timer  = new Timer(40, new ActionListener(){
        @Override
        public void actionPerformed(ActionEvent e) {
            if (sortingIsDone()) {
                ((Timer)e.getSource()).stop();
            } else {
                sortOnlyOneItem();
            }
            repaint();
        }
    });
    

    Your sortOnlyOneItem method should only, well, perform a sort for just one item. And have some sort of flag to check if the sorting is done, then stop the timer.


    Other notes:

    • You should be calling super.paintComponent in the paintComponent method, if you aren't going to paint the background yourself. Generally I always do though.

    Here's a complete example. I'm glad you figured it out on your own. I was working on this example before I saw that you got it.

    enter image description here

    import java.awt.Dimension;
    import java.awt.Graphics;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.util.Arrays;
    import java.util.Collections;
    
    import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.SwingUtilities;
    import javax.swing.Timer;
    
    public class SelectionSortAnimate extends JPanel {
    
        private static final int NUM_OF_ITEMS = 20;
        private static final int DIM_W = 400;
        private static final int DIM_H = 400;
        private static final int HORIZON = 350;
        private static final int VERT_INC = 15;
        private static final int HOR_INC = DIM_W / NUM_OF_ITEMS;
    
        private JButton startButton;
        private Timer timer = null;
        private JButton resetButton;
    
        Integer[] list;
        int currentIndex = NUM_OF_ITEMS - 1;
    
        public SelectionSortAnimate() {
            list = initList();
    
            timer = new Timer(200, new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    if (isSortingDone()) {
                        ((Timer) e.getSource()).stop();
                        startButton.setEnabled(false);
                    } else {
                        sortOnlyOneItem();
                    }
                    repaint();
                }
            });
            startButton = new JButton("Start");
            startButton.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    timer.start();
                }
            });
            resetButton = new JButton("Reset");
            resetButton.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    list = initList();
                    currentIndex = NUM_OF_ITEMS - 1;
                    repaint();
                    startButton.setEnabled(true);
                }
            });
            add(startButton);
            add(resetButton);
        }
    
        public boolean isSortingDone() {
            return currentIndex == 0;
        }
    
        public Integer[] initList() {
            Integer[] nums = new Integer[NUM_OF_ITEMS];
            for (int i = 1; i <= nums.length; i++) {
                nums[i - 1] = i;
            }
            Collections.shuffle(Arrays.asList(nums));
            return nums;
        }
    
        public void drawItem(Graphics g, int item, int index) {
            int height = item * VERT_INC;
            int y = HORIZON - height;
            int x = index * HOR_INC;
            g.fillRect(x, y, HOR_INC, height);
        }
    
        public void sortOnlyOneItem() {
            int currentMax = list[0];
            int currentMaxIndex = 0;
    
            for (int j = 1; j <= currentIndex; j++) {
                if (currentMax < list[j]) {
                    currentMax = list[j];
                    currentMaxIndex = j;
                }
            }
    
            if (currentMaxIndex != currentIndex) {
                list[currentMaxIndex] = list[currentIndex];
                list[currentIndex] = currentMax;
            }
            currentIndex--;
        }
    
        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            for (int i = 0; i < list.length; i++) {
                drawItem(g, list[i], i);
            }
        }
    
        @Override
        public Dimension getPreferredSize() {
            return new Dimension(DIM_W, DIM_H);
        }
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    JFrame frame = new JFrame("Sort");
                    frame.add(new SelectionSortAnimate());
                    frame.pack();
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                }
            });
        }
    }
    
    0 讨论(0)
提交回复
热议问题