Java swing在计算时重新绘制: animating sorting algorithm

标签 java swing sorting animation event-dispatch-thread

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

我想使用 Java Swing 开发类似于上面链接的东西。我有排序方法,并且在重新绘制时执行了操作,但是当我触发排序时,它没有显示条形图缓慢地自行排序,而是卡住,然后在数组完全排序后解冻。

我该如何解决这个问题? 编辑:抱歉忘记了代码。它是一个非常简单的图形用户界面。另一个用于排序的类对整个数组进行排序

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)

参见How to use a Swing Timer 。在 ActionListener 回调中进行“迭代”更新。例如,如果您想要为排序算法设置动画,则需要确定计时器回调的每个“迭代”需要更新的内容。然后每次迭代都会重新绘制 ui。

所以你的计时器可能看起来像这样

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

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

<小时/>

其他说明:

  • 如果您不打算自己绘制背景,则应该在 paintComponent 方法中调用 super.paintComponent。一般来说我总是这样做。
<小时/>

这是一个完整的示例。我很高兴你自己想出了办法。在我看到你明白之前我正在研究这个例子。

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

关于Java swing在计算时重新绘制: animating sorting algorithm,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24585911/

相关文章:

java - 在 Java J2ME 中使用 RecordStore

java - 二维字符串数组中基于整数的排序

java - 获取相关 ID 为 92 的元数据时出错 : {myTest=UNKNOWN_TOPIC_OR_PARTITION}

java - 创建自己的String类,系统首先打印出null

java - 如何制作一个像网络中那样的特定组合框?

java - 在 Java 中下载文件。多线程,这有用吗?

java - 当事件发生时绘制新的图形组件(即圆圈)

python - Numpy argsort 不稳定性

java - 如何仅在 Java 中将相同长度的 BitSet 设置为 true 的索引处对 int[] 进行排序

algorithm - 基数排序是唯一的非比较排序算法吗?