Java Swing 计算时重绘:动画排序算法 [英] Java swing repainting while computing: animating sorting algorithm

查看:26
本文介绍了Java Swing 计算时重绘:动画排序算法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

我想使用 Java Swing 开发类似于上面链接的东西.我有排序方法并且在重绘时做了,但是当我触发排序时,不是显示条形缓慢排序本身,而是在数组完全排序后冻结然后解冻.

I want to develop something similar to the link above using Java Swing. I have the sorting method and did while repaint but when I triggered the sorting, instead of showing the bars slowly sorting itself, it freezes and then unfreezes when the array has been fully sorted.

我该如何解决这个问题?抱歉忘记了代码.它是一个非常简单的gui.另一个用于排序的类对整个数组进行排序

How do I fix this? sorry forgot about the codes. its a very simple gui. and another class for sorting which sorts the whole array

public class SortGUI {
JFrame frame;
int frameWidth = 1000, frameHeight = 1000;
int panelWidth, panelHeight;
DrawPanel panel;
JPanel panel2;
JScrollPane scroll;
JViewport view;

static int[] S = new int[50000];

public static void main(String[] args) throws InterruptedException {
    SortGUI app = new SortGUI();
    initializeArray();        
    app.go(); 
}

public static void initializeArray()
{
         for (int i = 0; i < S.length; i++) {
     S[i] = (int) (Math.random() * 16581375);
     }
}

public void go() throws InterruptedException {
    //Frame
    frame = new JFrame();
    frame.setSize(frameWidth, frameHeight);
    frame.setVisible(true); 
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);  

    //panel
    panel = new DrawPanel();
    scroll = new JScrollPane(panel,JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);


    //Layout
    frame.add(scroll);
    frame.addKeyListener(new keyListener());

    while(true)
    {               
        panel.repaint();
    }
   }


public class DrawPanel extends JPanel
{   
    public DrawPanel()
    {
        this.setPreferredSize(new Dimension(50000,930));
    }

    public void paintComponent(Graphics g) 
    {          
        g.setColor(Color.WHITE);
        g.fillRect(0, 0, this.getWidth(), this.getHeight());
        for(int i = 0; i < S.length; i++)
        {
            int red = S[i] / 65025;
            int green = (S[i] > 65025)? S[i] % 65025 : 0;
            int blue = green;
            blue %= 255;
            green /= 255;

             g.setColor(new Color(red,green,blue));
            g.fillRect(i, 900 - (S[i] / 18500), 1, S[i] / 18500);
        }
    }
}

  public class keyListener implements KeyListener{


    public void keyTyped(KeyEvent ke) {

    }


    public void keyPressed(KeyEvent ke) {
      if(ke.getKeyChar() == '1')
      {
   sorter.bubbleSort(S);
      }
    }


    public void keyReleased(KeyEvent ke) { 
    }

  }
}

推荐答案

注意:我在问题被删除之前开始写这个

很可能您使用了一些循环机制并祈祷每次迭代,ui 都会更新.这是一个错误的假设.在循环完成之前,用户界面将不会更新.你正在做的是我们所说的阻塞事件调度线程(EDT)

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)

请参阅如何使用 Swing 计时器.在 ActionListener 回调中进行迭代" 更新.例如,如果您想为排序算法设置动画,您需要确定每次计时器回调的迭代" 需要更新什么.然后每次迭代都重新绘制 ui.

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

您的 sortOnlyOneItem 方法应该只对一个项目执行排序.并有某种标志来检查排序是否完成,然后停止计时器.

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.

其他注意事项:

  • 如果您不打算自己绘制背景,则应该在 paintComponent 方法中调用 super.paintComponent.不过一般我总是这样做.
  • 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.

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

这篇关于Java Swing 计算时重绘:动画排序算法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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