java.awt矩形的动画不符合要求

时间:2017-01-13 14:20:24

标签: java swing user-interface graphics

我正在尝试动画选择和放大的过程。插入排序算法,矩形按高度显示排序值。

当我的选择/插入排序算法发生单个更改时,我调用repaint(),但它似乎没有完全重绘它们,只有一些矩形发生了变化。在最终结果中,它实际上根本不显示完全排序的数组。

两种算法都经过测试和工作,因此问题似乎在于动画过程。

任何帮助?

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

1 个答案:

答案 0 :(得分:1)

首先,您不应该覆盖JFrame的绘制方法。而是覆盖paintComponent()的{​​{1}}以进行自定义绘图。您可以将JPanel用于此目的:

MyPanel

其次,避免使用null布局。在您的案例中,最好使用public class MyPanel extends JPanel{ public MyPanel(){ setBackground(Color.WHITE); } public synchronized void paintComponent(Graphics g) { super.paintComponent(g); // your paint code } } 之类的JFrame

此外,您必须了解BorderLayout。 GUI元素的操作必须在这个线程上进行。

您应该在EDT上设置GUI。您可以使用main-method中的SwingUtilities.invokeLater()执行此操作:

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

您应该考虑在单独的线程中处理动画,以便在EDT之外进行排序。这是一个关于它如何在原则上工作的小型演示,其中包含您的选择类型:

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

如您所见,我将用于更新选择排序的代码放入synchronized块,以便与paintComponent()方法同步。这是必要的,因为绘画发生在EDT上,而排序发生在不同于EDT的线程上。在示例中,我使用MyPanel对象作为监视器。