简体   繁体   English

java.awt 矩形的动画不按预期行事

[英]Animation of java.awt rectangles not acting as wanted

I am trying to animate the process of the Selection & Insertion sort algorithms with rectangles displaying sorted values by height.我正在尝试使用按高度显示排序值的矩形为选择和插入排序算法的过程设置动画。

I call repaint() when a single change occurs in my Select/Insert sort algorithms, but it does not seem to repaint them entirely, only some of the rectangles change.当我的选择/插入排序算法中发生单个更改时,我调用repaint() ,但它似乎并没有完全重新绘制它们,只有一些矩形发生了变化。 In the end result, it doesn't actually display the fully sorted array at all.最终,它实际上根本没有显示完全排序的数组。

Both algorithms are tested and work, so the problems seems to be with animating their process.这两种算法都经过了测试和工作,所以问题似乎在于它们的过程动画。

Any help?有什么帮助吗?

MyPaint.java我的画图

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.Timer;
import java.util.TimerTask;
public class MyPanel extends JPanel{
  private static int[] mainArr;
  private boolean reset = false;
  private Timer t = new Timer();
  private int[] tempArr;
    public MyPanel(){
       JPanel panel = new JPanel();
       panel.setPreferredSize(new Dimension(400, 400));
       panel.setBackground(Color.WHITE);
       panel.setLayout(new FlowLayout(FlowLayout.CENTER));
       //JButton selButton = new JButton("Select Sort");
       //panel.add(selButton);
       add(panel);      
    }   
    public static void main(String[] args) {
      SortDriver frame = new SortDriver();
      mainArr = frame.getArr();
      frame.setVisible(true);

    }
}

SortDriver.java排序驱动程序

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.Graphics;
public class SortDriver extends JFrame implements ActionListener {

        private int modeName;
        private JButton startButton;
        private JButton selButton;
        private JButton insButton;
        private JPanel mainPanel;
        private MyPanel panel;
        private int[] sortArr = new int[41];

        public SortDriver() {
                setLayout(null);
                setPreferredSize(new Dimension(420, 420));
                setResizable(false);
                setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                mainPanel = new JPanel();
                mainPanel.setBackground(Color.WHITE);
                mainPanel.setBounds(0, 0, 420, 420);
                mainPanel.setPreferredSize(new Dimension(400, 400));
                //mainPanel.setLayout(new FlowLayout(FlowLayout.CENTER));
                add(mainPanel);

                //Buttons 
                startButton = new JButton("Start");
                startButton.addActionListener(this);
                mainPanel.add(startButton);
                selButton = new JButton("Select Sort");
                selButton.addActionListener(this);
                mainPanel.add(selButton);
                insButton = new JButton("Insert Sort");
                insButton.addActionListener(this);
                mainPanel.add(insButton);


                //Panel
                panel = new MyPanel();

                mainPanel.add(panel);
                //Array                              
                for(int i = 0; i <= 40; i++){
                  sortArr[i] = 0; 
                }
                for(int i = 0; i <= 40; i++){
                  int random = (int)(Math.random() * 50 + 1);
                  sortArr[i] = random; 
                }
                //Final
                pack();
        }
        public void paint(Graphics g) {
          for(int i = 0; i <= 40; i++){
            g.fillRect(i * 10, 100, 5, sortArr[i]);
          }      
        }

        public void selectionSort (int[] list){       
          int min;       
          int temp;        
          for (int index = 0; index < list.length-1; index++){          
            min = index;          
            for (int scan = index+1; scan < list.length; scan++)             
              if (list[scan] - (list[min]) < 0) min = scan;           

      // Swap the values          
            temp = list[min];          
            list[min] = list[index];
            list[index] = temp;
            repaint();
          }
          //for(int i = 0; i <= list.length; i++){
          //  System.out.println(list[i]); 
          //}
        }
        public void insertionSort (int[] list){       
          for (int index = 1; index < list.length; index++){          
            int key = list[index];          
            int position = index;           

            //  Shift larger values to the right          
            while (position > 0 && key - (list[position-1]) < 0){             
              list[position] = list[position-1];
              position--;
              repaint();
            }          
            list[position] = key;       
          }    
        }
        public void actionPerformed(ActionEvent event) {
          if (event.getSource() == selButton) {
            modeName = 1;
          }
          else if (event.getSource() == insButton) {
            modeName = 2;
          }
          else if (event.getSource() == startButton) {
            if(modeName == 1){
              selectionSort(sortArr);
            }
            if(modeName == 2){
              insertionSort(sortArr);
            }
          }
        }
        public int getMode(){
          return modeName; 
        }
        public int[] getArr(){
          return sortArr; 
        }
}

First of all, you should not override the paint method of your JFrame .首先,您不应覆盖JFrame的 paint 方法。 Rather override paintComponent() of a JPanel for customize drawing.而重写paintComponent()一个的JPanel用于定制图。 You could use MyPanel for this purpose:您可以为此目的使用MyPanel

public class MyPanel extends JPanel{

    public MyPanel(){
       setBackground(Color.WHITE);             
    }   

    public synchronized void paintComponent(Graphics g) {
        super.paintComponent(g);
        // your paint code    
    }

}

Secondly, avoid using null layout.其次,避免使用空布局。 Better use something like BorderLayout in your case for the JFrame .最好在JFrame的情况下使用BorderLayout 之类的东西。

Also, you have to be aware of the Event Dispatch Thread .此外,您必须了解Event Dispatch Thread Manipulations on GUI elements have to happen on this thread.对 GUI 元素的操作必须在此线程上进行。

You should setup your GUI on the EDT.您应该在 EDT 上设置您的 GUI。 You can do this using SwingUtilities.invokeLater() in your main-method:你可以在你的主方法中使用SwingUtilities.invokeLater()来做到这一点:

SwingUtilities.invokeLater(() -> {
    SortDriver frame = new SortDriver();
    mainArr = frame.getArr();
    frame.setVisible(true);
});

You should consider to handle animation in a separate thread so that sorting happens outside of the EDT.您应该考虑在单独的线程中处理动画,以便在 EDT 之外进行排序。 Here is a small demo on how it could work in principle featuring your selection sort:这是一个关于它原则上如何工作的小演示,以您的选择排序为特色:

new Thread(() -> {
  int min;       
  int temp;  

  final int delayMillis = 100;
  long startTickTime = System.nanoTime();
  for (int index = 0; index < list.length-1; index++){          
    synchronized(myPanel){
        min = index;          
        for (int scan = index+1; scan < list.length; scan++)             
          if (list[scan] - (list[min]) < 0) min = scan;           

        // Swap the values          
        temp = list[min];          
        list[min] = list[index];
        list[index] = temp;
    }
    myPanel.repaint();
    try {
        TimeUnit.NANOSECONDS.sleep(delayMillis*1000000-System.nanoTime()+startTickTime);
        startTickTime = System.nanoTime();
    } catch (Exception e) {                 
        e.printStackTrace();
    }
  }
}).start();

As you can see I put the code for updating the selection sort into a synchronized block so that it is synchronized with the paintComponent() method.如您所见,我将更新选择排序的代码放入synchronized块中,以便与paintComponent()方法同步。 This is necessary, because painting happens on the EDT while sorting happens on a thread different from the EDT.这是必要的,因为绘制发生在 EDT 上,而排序发生在与 EDT 不同的线程上。 In the example I used the MyPanel object as monitor.在示例中,我使用MyPanel对象作为监视器。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM