2013-04-02 2 views
2

Хорошо, поэтому я некоторое время работал над этим кодом, который показывает, как работают алгоритмы сортировки. Прямо сейчас я работаю там, где он сортирует несколько графиков с одним и тем же типом, но мне нужно, чтобы каждый график выполнял другой вид в одно и то же время. Я исследовал и пытался решить это в течение нескольких дней, и теперь у меня есть туннельное видение. Я отправлю свой код на случай, если мои объяснения смущают. Я чувствую, что это может принести пользу многим людям, работающим с графикой Java, и любая помощь будет оценена по достоинству.java multiple graphics

import java.applet.Applet; 
import java.awt.*; 
import java.awt.event.*; 
import java.util.Random; 
import java.util.StringTokenizer; 
import java.util.Scanner; 


public class Sort extends Applet { 

/** Constructor. Only for starting the sorting animation as applet. */ 
public Sort() {} 


/** For starting the sorting animation as application. */ 
public static void main(String[] argv) { 
    Frame _aFrame = new Frame("Sort Animations"); 
    _aFrame.setBackground(Color.white); 
    _aFrame.setPreferredSize(new Dimension(2700,1000)); 

    Scanner in = new Scanner(System.in); 
    int sizeOfArray; 
    System.out.println("How many numbers do you want to sort?"); 
    sizeOfArray = in.nextInt(); 


    _aFrame.addWindowListener(
           new WindowAdapter() { 
     public void windowClosing(WindowEvent e) { System.exit(0); } 
    } 
          ); 

    _aFrame.setLayout(new BorderLayout()); 
    _aFrame.add(new SortPanel(sizeOfArray)); 
    _aFrame.pack(); 
    _aFrame.setVisible(true); 
} 

} 



class SortPanel extends Panel implements Runnable { 

/** button triggering the sort animation */ 
private Button aSortButton_ = new Button("sort"); 
/** choice item for selecting the sort algorithm */ 
private Choice aChoice_ = new Choice(); 
/** component for handling the animation */ 
private ArrayCanvas anArrayCanvas_; 


///////////////////////////////////////////////////////////////////////////// 

/** 
* Constructor. 
* 
* @param length no of elements of the array 
* @param aBarColor the color the elements representing bars will be drawn in 
* 
* @exception IllegalArgumentException if the array <code>length</code> is 
*   to big to display (ie <code>length</code> is bigger than 
*   <code>BAR_WIDTH</code> or <code>BAR_HEIGHT</code>). 
*/ 
public SortPanel(int arraySize) { 
    setLayout(new BorderLayout()); 


    aSortButton_.addActionListener(
       new  ActionListener() { 
     public void actionPerformed(ActionEvent e) { 
      new Thread(SortPanel.this).start(); 
     } 
    } 
       ); 


    anArrayCanvas_ = new ArrayCanvas(arraySize); 
    for (int i=0; i<ArrayCanvas.SORT_NAMES.length; ++i) 
     aChoice_.add(ArrayCanvas.SORT_NAMES[i]); 

    // add buttons at top: 
    Panel _aTopPanel = new Panel(); 
    _aTopPanel.add(aSortButton_); 
    add(_aTopPanel, BorderLayout.NORTH); 

    // add choice and ArrayCanvas below: 
    Panel _aPanel = new Panel(); 
    _aPanel.setLayout(new BorderLayout()); 
    Panel _aChoicePanel = new Panel(); 
    _aChoicePanel.add(aChoice_); 
    _aPanel.add(_aChoicePanel, BorderLayout.NORTH); 
    _aPanel.add(anArrayCanvas_, BorderLayout.CENTER); 

    add(_aPanel, BorderLayout.CENTER); 

    Panel _aBottomPanel = new Panel(); 
    add(_aBottomPanel, BorderLayout.SOUTH); 
} 

///////////////////////////////////////////////////////////////////////////// 

/** Runs the sorting animation. */ 
public void run() { 
    aSortButton_.setEnabled(false); 
    double time = System.currentTimeMillis(); 
    anArrayCanvas_.sort(aChoice_.getSelectedItem()); 
    aSortButton_.setEnabled(true); 
} 
} 

class ArrayCanvas extends Canvas { 

/** Labels of available sorting algorithms. */ 
public final static String[] SORT_NAMES = { "bubble sort", "insertion sort", "shell sort", "heap sort", "merge sort", "quick sort",}; 

/** offset between bars and border in x-directions (left and right) */ 
public final static int OFFSET_X   = 5; 
/** offset between bars and border in y-directions (top and bottom) */ 
public final static int OFFSET_Y   = 5; 
/** horizontal size of all bars together */ 
public final static int BAR_WIDTH  = 350; 
/** (max) vertical horizontal size of bars together */ 
public final static int BAR_HEIGHT  = 250; 
/** milliseconds to sleep after a swap in the sorting animation */ 
public final static int SLEEP_AFTER_SWAP = 20; 

/** used for random permutation of the array elements */ 
private static Random aRandom_ = new Random(System.currentTimeMillis()); 
/** the array to display */ 
private int[] anArrayOfInt_; 
/** offscreen buffer */ 
private Image image_; 
/** graphics of the offscreen buffer */ 
private Graphics offscreenGraphics_; 




///////////////////////////////////////////////////////////////////////////// 

/** 
* Constructor. 
* 
* @param length no of elements of the array 
* 
* @exception IllegalArgumentException if the array <code>length</code> is 
*   to big to display (ie <code>length</code> is bigger than 
*   <code>BAR_WIDTH</code> or <code>BAR_HEIGHT</code>). 
*/ 
public ArrayCanvas(int length) { 
    if (length > BAR_WIDTH || length > BAR_HEIGHT) 
     throw new IllegalArgumentException("array to big: "+length); 
    anArrayOfInt_ = new int[length]; 
    for (int i=0; i<length; ++i) 
     anArrayOfInt_[i] = i+1; 
    permute(); 
    addMouseListener(
        new MouseAdapter() { 
     public void mouseClicked(MouseEvent e) { 
      repaint(); 
     } 
    } 
        ); 
} 

///////////////////////////////////////////////////////////////////////////// 


// overloaded for double buffering 
public void update(Graphics aGraphics) { 
    paint(aGraphics); 
} 

/** displays the array */ 
public void paint(Graphics aGraphics) { 
    int _deltaX = 0; 
    int w = BAR_WIDTH/anArrayOfInt_.length; 
    if (w > 1) { 
     --w; 
     ++_deltaX; 
    } 
    int _heightFactor = BAR_HEIGHT/anArrayOfInt_.length; 
    if (offscreenGraphics_ == null) { 
     image_ = createImage(getSize().width, getSize().height); 
     offscreenGraphics_ = image_.getGraphics(); 
    } 

    offscreenGraphics_.setColor(getBackground()); 
    offscreenGraphics_.fillRect(0, 0, getSize().width-1, getSize().height-1); 

    offscreenGraphics_.setColor(Color.black); 
    //offscreenGraphics_.drawRect(0, 0, getSize().width-1, getSize().height-1); 
    offscreenGraphics_.translate(OFFSET_X, OFFSET_Y); 
    for (int i=0; i<anArrayOfInt_.length; ++i) { 
     int h = _heightFactor*anArrayOfInt_[i]; 
     offscreenGraphics_.setColor(Color.blue); 
     offscreenGraphics_.fillRect((w+_deltaX)*i, BAR_HEIGHT-h, w, h); 
     if(anArrayOfInt_[i]==(i+1)){ 
      offscreenGraphics_.setColor(Color.red); 
      offscreenGraphics_.fillRect((w+_deltaX)*i, BAR_HEIGHT-h, w, _heightFactor); 
     } 
    } 

    offscreenGraphics_.translate(-OFFSET_X, -OFFSET_Y); 
    aGraphics.drawImage(image_, 0, 0, this); 
    aGraphics.drawImage(image_, 475, 0, this); 
    aGraphics.drawImage(image_, 950, 0, this); 
    aGraphics.drawImage(image_, 0, 350, this); 
    aGraphics.drawImage(image_, 475, 350, this); 
    aGraphics.drawImage(image_, 950, 350, this); 

} 

public Dimension getMinimumSize() { 
    return new Dimension(BAR_WIDTH+2*OFFSET_X, BAR_HEIGHT+2*OFFSET_Y); 
} 

public Dimension getPreferredSize() { 
    return getMinimumSize(); 
} 

/////////////////////////////////////////////////// 

/** random permutation of array entries */ 
public void permute() { 
    for (int i=anArrayOfInt_.length-1; i>0; --i) { 
     int j = Math.abs(aRandom_.nextInt()) % (i+1); 
     swap(anArrayOfInt_,i,j); 
    } 
} 


/** animated sort */ 
public void sort(String aSortNameString) { 
    mySort(aSortNameString); 
} 

/////////////////////////////////////////////////// 


private void mySort(String aSortNameString) { 

    if (aSortNameString.equals("bubble sort")) { 
     bubbleSort(anArrayOfInt_); 

    } 

    if (aSortNameString.equals("insertion sort")) { 
     insertionSort(anArrayOfInt_); 
    } 

    if (aSortNameString.equals("selection sort")) { 
     selectionSort(anArrayOfInt_); 
    } 

    if (aSortNameString.equals("shell sort")) { 
     shellSort(anArrayOfInt_); 

    } 
    if (aSortNameString.equals("heap sort")) { 
     heapSort(anArrayOfInt_); 

    } 
    if (aSortNameString.equals("merge sort")) { 
     mergeSort(anArrayOfInt_, 0, anArrayOfInt_.length-1); 

    } 
    if (aSortNameString.equals("quick sort")) { 
     qSort(anArrayOfInt_, 0, anArrayOfInt_.length-1); 

    } 

} 

/** 
* swaps the two array elements, redisplays the array in its canvas, 
* and waits a moment. 
*/ 
private void swap(int[] anArrayOfInt, int i, int j) { 
    int x = anArrayOfInt[i]; 
    anArrayOfInt[i] = anArrayOfInt[j]; 
    anArrayOfInt[j] = x; 
    repaint(); 
    try { Thread.sleep(SLEEP_AFTER_SWAP); } catch (InterruptedException e) {} 
} 


///////////////////////////////////////////////////////////////////////////// 
//       SORTING ALGORITHMS        // 
///////////////////////////////////////////////////////////////////////////// 

/** bubble sort */ 
private void bubbleSort(int[] anArrayOfInt) { 
    for (int i=0; i<anArrayOfInt.length; ++i) 
     for (int j=1; j<anArrayOfInt.length-i; ++j) 
      if (anArrayOfInt[j-1]>anArrayOfInt[j]) { 
       swap(anArrayOfInt, j-1, j); 
      } 
} 



/** insertion sort */ 
private void insertionSort(int[] anArrayOfInt) { 
    for (int i=0; i<anArrayOfInt.length; ++i) 
     for (int j=i-1; j>=0 && anArrayOfInt[j]>anArrayOfInt[j+1]; --j) 
      swap(anArrayOfInt, j, j+1); 
} 


/** selection sort */ 
private void selectionSort(int[] anArrayOfInt) { 
    for (int i=0; i<anArrayOfInt.length-1; ++i) { 
     for (int j=i+1; j<anArrayOfInt.length; ++j) 
      if (anArrayOfInt[j] < anArrayOfInt[i]) 
       swap(anArrayOfInt, i, j); 
    } 
} 

/** shell sort */ 
private void shellSort(int[] anArrayOfInt) { 
    // TODO: calculate needed STEPS-elements instead of using an array 
    //  (STEPS[i+1] = 3*STEPS[i]+1) 
    for (int i=0; i<STEPS.length; ++i) { 
     int _delta = STEPS[i]; 
     if (_delta >= anArrayOfInt.length) 
      continue; 
     for (int j=_delta; j<anArrayOfInt.length; ++j) 
      for (int k=j; k-_delta>=0 && anArrayOfInt[k]<anArrayOfInt[k- _delta]; 
       k-=_delta) 
       swap(anArrayOfInt, k, k-_delta); 
    } 
} 

/** used by shell sort */ 
private final static int[] STEPS = { 1093, 364, 121, 40, 13, 4, 1 }; 

/** heap sort */ 
private void heapSort(int[] anArrayOfInt) { 
    int r = anArrayOfInt.length-1; 
    for (int l = anArrayOfInt.length/2 ; l>=0; --l) 
     sift(anArrayOfInt, l, r); 
    while (r > 0) { 
     swap(anArrayOfInt, 0, r); 
     sift(anArrayOfInt, 0, --r); 
    } 
} 

/** auxiliary function for heap sort. */ 
private void sift(int[] anArrayOfInt, int l, int r) { 
    if (r==l) 
     return; 
    int i = l, j = 2*l; 
    int x = anArrayOfInt[i]; 
    if (j<r && anArrayOfInt[j]<anArrayOfInt[j+1]) 
     ++j; 
    while (j<=r && x<=anArrayOfInt[j]) { 
     swap(anArrayOfInt, i, j); 
     i = j; j = 2*j; 
     if (j<r && anArrayOfInt[j]<anArrayOfInt[j+1]) 
      ++j; 
    } 
} 

/** quick sort (pivot=(l+r)/2)*/ 
private void qSort(int[] anArrayOfInt, int l, int r) { 
    if (l >= r) 
     return; 
    swap(anArrayOfInt, l, (l+r)/2); // TODO: more clever pivot 
    int _last = l; 
    for (int i=l+1; i<=r; ++i) 
     if (anArrayOfInt[i] < anArrayOfInt[l]) 
      swap(anArrayOfInt, ++_last, i); 
    swap(anArrayOfInt, l, _last); 
    qSort(anArrayOfInt, l, _last-1); 
    qSort(anArrayOfInt, _last+1, r); 
} 


/** merge sort */ 
private void mergeSort(int[] anArrayOfInt, int l, int r) { 
    int[][] B = new int[2][r+1]; 
    mergeSort16(anArrayOfInt, B, l, r); 
} 

private void mergeSort16(int[] anArrayOfInt, int[][] B, int l, int r) { 
    if (l >= r) 
     return; 
    int _last = (l+r)/2; 
    mergeSort16(anArrayOfInt, B, l, _last); 
    mergeSort16(anArrayOfInt, B, _last+1, r); 
    merge6(anArrayOfInt, B, l, _last, r); 
} 
/** auxiliary function for merge sort */ 
protected void merge6(int[] anArrayOfInt, int[][] B, int l, int q, int r) { 
    for (int i=l;i<=q;i++) { 
     B[0][i] = i; 
     B[1][i] = i; 
    } 
    for (int i=r;i>q;i--) { 
     B[0][i] = r+q+1-i; 
     B[1][i] = r+q+1-i; 
    } 
    int i = l; 
    int j = r; 
    for (int k=l; k<r;k++) { 
     int s = B[0][i]; 
     int t = B[0][j]; 
     if (anArrayOfInt[s]<=anArrayOfInt[t]) { 
      i++; 
     } else { 
      s = t; 
      j--; 
     } 
     swap(anArrayOfInt, s, k); 
     t = B[1][k]; 
     B[0][t] = s; 
     B[1][s] = t; 
    } 
} 

} 
+0

В чем смысл перехода от «Applet», когда вы просто создаете «Рамку»? – MadProgrammer

+0

Дамп AWT и использование Swing – MadProgrammer

ответ

8

Для каждого графа сортировки требуется какая-то модель, которая должна содержать текущее состояние каждого вида. Это, вероятно, означало бы добавление вашего списка int s в отдельный список для сортировки.

Вам также понадобится какой-то механизм, который позволит вам пройти через каждый алгоритм сортировки и сообщить ему перейти к следующему шагу в своем алгоритме, что позволит вам контролировать, когда каждый алгоритм сортировки обновляется и, следовательно, управляет, когда экран обновляется.

Обновлено

Основываясь на комментарии от ОП, в основном, я вырван алгоритма сортировки в качестве отдельного интерфейса. Каждый алгоритм должен будет расширяться от этого интерфейса, но он обеспечивает основные требования, позволяющие пользовательскому интерфейсу отображать анимацию сортировки.

Bellow - это базовая реализация, в то время как она основана на Swing, если потребуется, это не будет растянуть, чтобы заставить ее работать с AWT.

enter image description here

import java.awt.BorderLayout; 
import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.EventQueue; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.util.ArrayList; 
import java.util.List; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.Timer; 
import javax.swing.UIManager; 
import javax.swing.UnsupportedLookAndFeelException; 
import javax.swing.event.ChangeEvent; 
import javax.swing.event.ChangeListener; 

public class TestSort { 

    public static void main(String[] args) { 
     new TestSort(); 
    } 

    public TestSort() { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       try { 
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
       } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { 
       } 

       SortPane sortPane = new SortPane(); 
       int values[] = new int[10]; 
       for (int index = 0; index < values.length; index++) { 
        values[index] = (int)Math.round(Math.random() * 100f); 
       } 
       BubbleSort sorter = new BubbleSort(values); 
       sortPane.setSorter(sorter); 

       JFrame frame = new JFrame("Testing"); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       frame.setLayout(new BorderLayout()); 
       frame.add(sortPane); 
       frame.pack(); 
       frame.setLocationRelativeTo(null); 
       frame.setVisible(true); 
       sorter.sort(); 
      } 
     }); 
    } 

    public class SortPane extends JPanel { 

     private Sorter sorter; 
     private ChangeHandler changeHandler; 
     private int maxValue; 

     @Override 
     public Dimension getPreferredSize() { 
      return new Dimension(200, 200); 
     } 

     @Override 
     protected void paintComponent(Graphics g) { 
      super.paintComponent(g); 
      Graphics2D g2d = (Graphics2D) g.create(); 
      int values[] = getSorter().getValues(); 
      int width = getWidth() - 1; 
      int height = getHeight() - 1; 
      int colWidth = Math.round((float)width/(float)values.length); 
      int x = 0; 
      Color fill = Color.YELLOW; 
      Color highlight = null; 
      switch (getSorter().getState()) { 
       case Sorting: 
        fill = Color.BLUE; 
        highlight = Color.RED; 
        break; 
       case Done: 
        fill = Color.GREEN; 
        break; 
      } 
      for (int index = 0; index < values.length; index++) { 
       g2d.setColor(fill); 
       int value = values[index]; 
       int colHeight = (int)((float)height * ((float)value/(float)maxValue)); 
       g2d.fillRect(x, height - colHeight, colWidth - 1, colHeight); 
       if (getSorter().isActiveIndex(index) && highlight != null) { 
        g2d.setColor(highlight); 
        g2d.drawRect(x, height - colHeight, colWidth - 1, colHeight); 
       } 
       x += colWidth; 
      } 
      g2d.dispose(); 
     } 

     public Sorter getSorter() { 
      return sorter; 
     } 

     public void setSorter(Sorter value) { 
      if (sorter != value) { 
       if (sorter != null) { 
        sorter.removeChangeListener(getChangeHandler()); 
       } 
       sorter = value; 
       if (sorter != null) { 
        sorter.addChangeListener(getChangeHandler()); 
        maxValue = 0; 
        for (int intValue : sorter.getValues()) { 
         maxValue = Math.max(maxValue, intValue); 
        } 
       } 
       repaint(); 
      } 
     } 

     public ChangeHandler getChangeHandler() { 
      if (changeHandler == null) { 
       changeHandler = new ChangeHandler(); 
      } 
      return changeHandler; 
     } 

     public class ChangeHandler implements ChangeListener { 
      @Override 
      public void stateChanged(ChangeEvent e) { 
       repaint(); 
      } 
     } 

    } 

    public interface Sorter { 

     public enum State { 
      Waiting, 
      Sorting, 
      Done 
     } 

     public void addChangeListener(ChangeListener listener); 
     public void removeChangeListener(ChangeListener listener); 
     public int[] getValues(); 
     public void sort(); 
     public State getState(); 
     public boolean isActiveIndex(int index); 
    } 

    public abstract class AbstracSorter implements Sorter { 

     private List<ChangeListener> listeners; 
     private int[] values; 
     private State state = State.Waiting; 
     private List<Integer> activeIndices; 

     public AbstracSorter(int[] values) { 
      this.values = values; 
      listeners = new ArrayList<>(25); 
      activeIndices = new ArrayList<>(2); 
     } 

     @Override 
     public State getState() { 
      return state; 
     } 

     public void setState(State value) { 
      if (value != state) { 
       state = value; 
       fireStateChanged(); 
      } 
     } 

     @Override 
     public int[] getValues() { 
      return values; 
     } 

     @Override 
     public void addChangeListener(ChangeListener listener) { 
      listeners.add(listener); 
     } 

     @Override 
     public void removeChangeListener(ChangeListener listener) { 
      listeners.remove(listener); 
     } 

     protected void fireStateChanged() { 
      if (listeners.size() > 0) { 
       ChangeEvent evt = new ChangeEvent(this); 
       for (ChangeListener listener : listeners) { 
        listener.stateChanged(evt); 
       } 
      } 
     } 

     @Override 
     public boolean isActiveIndex(int index) { 
      return activeIndices.contains(index); 
     } 

     protected void setActiveIndicies(int lower, int upper) { 
      activeIndices.clear(); 
      activeIndices.add(lower); 
      activeIndices.add(upper); 
      fireStateChanged(); 
     } 

     protected void swap(int[] anArrayOfInt, int i, int j) { 
      setActiveIndicies(i, j); 
      int x = anArrayOfInt[i]; 
      anArrayOfInt[i] = anArrayOfInt[j]; 
      anArrayOfInt[j] = x; 
      fireStateChanged(); 
     } 
    } 

    public class BubbleSort extends AbstracSorter { 

     private int outter = 0; 
     private int inner = 0; 

     public BubbleSort(int[] values) { 
      super(values); 
     } 

     @Override 
     public void sort() { 
      setState(State.Sorting); 
      outter = 0; 
      inner = 1; 
      Timer timer = new Timer(250, new ActionListener() { 
       @Override 
       public void actionPerformed(ActionEvent e) { 
        int[] values = getValues(); 
        inner++; 
        if (inner >= values.length - outter) { 
         outter++; 
         inner = 1; 
        } 

        if (outter < values.length) { 
         if (values[inner - 1] > values[inner]) { 
          swap(values, inner - 1, inner); 
         } else { 
          setActiveIndicies(inner - 1, inner); 
         } 
        } else { 
         ((Timer)e.getSource()).stop(); 
         setState(State.Done); 
        } 
       } 
      }); 
      timer.setRepeats(true); 
      timer.start(); 
     } 
    } 
} 

Пример использования массива источника

import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.EventQueue; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.GridLayout; 
import java.awt.Insets; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.util.ArrayList; 
import java.util.List; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.Timer; 
import javax.swing.UIManager; 
import javax.swing.UnsupportedLookAndFeelException; 
import javax.swing.border.CompoundBorder; 
import javax.swing.border.EmptyBorder; 
import javax.swing.border.LineBorder; 
import javax.swing.event.ChangeEvent; 
import javax.swing.event.ChangeListener; 

public class TestSort { 

    public static void main(String[] args) { 
     new TestSort(); 
    } 
    private List<Sorter> sorters; 

    public TestSort() { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       try { 
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
       } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { 
       } 

       sorters = new ArrayList<>(2); 
       int values[] = new int[10]; 
       for (int index = 0; index < values.length; index++) { 
        values[index] = (int) Math.round(Math.random() * 100f); 
       } 

       JFrame frame = new JFrame("Testing"); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       frame.setLayout(new GridLayout(0, 2)); 
       frame.add(createBubbleSortPane(values)); 
       frame.add(createBubbleSortPane(values)); 
       frame.pack(); 
       frame.setLocationRelativeTo(null); 
       frame.setVisible(true); 

       for (Sorter sorter : sorters) { 
        sorter.sort(); 
       } 
      } 
     }); 
    } 

    protected SortPane createBubbleSortPane(int[] values) { 
     SortPane sortPane = new SortPane(); 
     BubbleSort sorter = new BubbleSort(values); 
     sortPane.setSorter(sorter); 

     sortPane.setBorder(new CompoundBorder(new LineBorder(Color.GRAY), new EmptyBorder(8, 8, 8, 8))); 

     sorters.add(sorter); 

     return sortPane; 
    } 

    public class SortPane extends JPanel { 

     private Sorter sorter; 
     private ChangeHandler changeHandler; 
     private int maxValue; 

     @Override 
     public Dimension getPreferredSize() { 
      return new Dimension(200, 200); 
     } 

     @Override 
     protected void paintComponent(Graphics g) { 
      super.paintComponent(g); 
      Graphics2D g2d = (Graphics2D) g.create(); 
      int values[] = getSorter().getValues(); 
      Insets insets = getInsets(); 
      int width = getWidth() - 1 - (insets.left + insets.right); 
      int height = getHeight() - 1 - (insets.top + insets.bottom); 
      int colWidth = Math.round((float) width/(float) values.length); 
      int x = insets.left; 
      Color fill = Color.YELLOW; 
      Color highlight = null; 
      switch (getSorter().getState()) { 
       case Sorting: 
        fill = Color.BLUE; 
        highlight = Color.RED; 
        break; 
       case Done: 
        fill = Color.GREEN; 
        break; 
      } 
      for (int index = 0; index < values.length; index++) { 
       g2d.setColor(fill); 
       int value = values[index]; 
       int colHeight = (int) ((float) height * ((float) value/(float) maxValue)); 
       g2d.fillRect(x, insets.top + height - colHeight, colWidth - 1, colHeight); 
       if (getSorter().isActiveIndex(index) && highlight != null) { 
        g2d.setColor(highlight); 
        g2d.drawRect(x, insets.top + height - colHeight, colWidth - 1, colHeight); 
       } 
       x += colWidth; 
      } 
      g2d.dispose(); 
     } 

     public Sorter getSorter() { 
      return sorter; 
     } 

     public void setSorter(Sorter value) { 
      if (sorter != value) { 
       if (sorter != null) { 
        sorter.removeChangeListener(getChangeHandler()); 
       } 
       sorter = value; 
       if (sorter != null) { 
        sorter.addChangeListener(getChangeHandler()); 
        maxValue = 0; 
        for (int intValue : sorter.getValues()) { 
         maxValue = Math.max(maxValue, intValue); 
        } 
       } 
       repaint(); 
      } 
     } 

     public ChangeHandler getChangeHandler() { 
      if (changeHandler == null) { 
       changeHandler = new ChangeHandler(); 
      } 
      return changeHandler; 
     } 

     public class ChangeHandler implements ChangeListener { 

      @Override 
      public void stateChanged(ChangeEvent e) { 
       repaint(); 
      } 
     } 
    } 

    public interface Sorter { 

     public enum State { 

      Waiting, 
      Sorting, 
      Done 
     } 

     public void addChangeListener(ChangeListener listener); 

     public void removeChangeListener(ChangeListener listener); 

     public int[] getValues(); 

     public void sort(); 

     public State getState(); 

     public boolean isActiveIndex(int index); 
    } 

    public abstract class AbstracSorter implements Sorter { 

     private List<ChangeListener> listeners; 
     private int[] values; 
     private State state = State.Waiting; 
     private List<Integer> activeIndices; 

     public AbstracSorter(int[] values) { 
      this.values = new int[values.length]; 
      System.arraycopy(values, 0, this.values, 0, values.length); 
      listeners = new ArrayList<>(25); 
      activeIndices = new ArrayList<>(2); 
     } 

     @Override 
     public State getState() { 
      return state; 
     } 

     public void setState(State value) { 
      if (value != state) { 
       state = value; 
       fireStateChanged(); 
      } 
     } 

     @Override 
     public int[] getValues() { 
      return values; 
     } 

     @Override 
     public void addChangeListener(ChangeListener listener) { 
      listeners.add(listener); 
     } 

     @Override 
     public void removeChangeListener(ChangeListener listener) { 
      listeners.remove(listener); 
     } 

     protected void fireStateChanged() { 
      if (listeners.size() > 0) { 
       ChangeEvent evt = new ChangeEvent(this); 
       for (ChangeListener listener : listeners) { 
        listener.stateChanged(evt); 
       } 
      } 
     } 

     @Override 
     public boolean isActiveIndex(int index) { 
      return activeIndices.contains(index); 
     } 

     protected void setActiveIndicies(int lower, int upper) { 
      activeIndices.clear(); 
      activeIndices.add(lower); 
      activeIndices.add(upper); 
      fireStateChanged(); 
     } 

     protected void swap(int[] anArrayOfInt, int i, int j) { 
      setActiveIndicies(i, j); 
      int x = anArrayOfInt[i]; 
      anArrayOfInt[i] = anArrayOfInt[j]; 
      anArrayOfInt[j] = x; 
      fireStateChanged(); 
     } 
    } 

    public class BubbleSort extends AbstracSorter { 

     private int outter = 0; 
     private int inner = 0; 

     public BubbleSort(int[] values) { 
      super(values); 
     } 

     @Override 
     public void sort() { 
      setState(State.Sorting); 
      outter = 0; 
      inner = 1; 
      Timer timer = new Timer(250, new ActionListener() { 
       @Override 
       public void actionPerformed(ActionEvent e) { 
        int[] values = getValues(); 
        inner++; 
        if (inner >= values.length - outter) { 
         outter++; 
         inner = 1; 
        } 

        if (outter < values.length) { 
         if (values[inner - 1] > values[inner]) { 
          swap(values, inner - 1, inner); 
         } else { 
          setActiveIndicies(inner - 1, inner); 
         } 
        } else { 
         ((Timer) e.getSource()).stop(); 
         setState(State.Done); 
        } 
       } 
      }); 
      timer.setRepeats(true); 
      timer.start(); 
     } 
    } 
} 

Пример вставки сортировщик

Это пример использования Thread в качестве основного рода двигателя вместо Swing Timer

public class InsertionSorter extends AbstracSorter { 

    public InsertionSorter(int[] values) { 
     super(values); 
    } 

    @Override 
    public void sort() { 
     setState(State.Sorting); 
     new Thread(new SortRunnable()).start(); 
    } 

    @Override 
    protected void swap(int[] anArrayOfInt, int i, int j) { 
     setActiveIndicies(i, j); 
     int x = anArrayOfInt[i]; 
     anArrayOfInt[i] = anArrayOfInt[j]; 
     anArrayOfInt[j] = x; 
     try { 
      SwingUtilities.invokeAndWait(new Runnable() { 
       @Override 
       public void run() { 
        fireStateChanged(); 
       } 
      }); 
     } catch (InterruptedException | InvocationTargetException exp) { 
      exp.printStackTrace(); 
     } 
    } 

    public class SortRunnable implements Runnable { 

     @Override 
     public void run() { 
      int[] values = getValues(); 
      for (int i = 0; i < values.length; ++i) { 
       for (int j = i - 1; j >= 0 && values[j] > values[j + 1]; --j) { 
        try { 
         Thread.sleep(250); 
        } catch (InterruptedException ex) { 
        } 
        swap(values, j, j + 1); 
       } 
      } 
      SwingUtilities.invokeLater(new Runnable() { 
       @Override 
       public void run() { 
        setState(State.Done); 
       } 
      }); 
     } 
    } 
} 
+0

Можно ли сделать каждую гистограмму отдельным объектом, а затем вызвать различный вид на каждом из своих массивов? – man123456

+0

Ну, в сущности, да. Вам нужно каким-то образом «установить» сортировщика на каждый график, чтобы сортировщик мог рассказать график, когда он должен обновляться (возможно, через какой-либо слушатель) – MadProgrammer

+0

Я попытался выполнить ваш код выше, и он говорит о незаконном запуске типа для слушателей = новый ArrayList <> (25); и activeIndices = new ArrayList <> (2); – man123456