swing绘图 - java多个图形



java绘图 (1)

好的,我一直在研究这段代码,显示了排序算法的工作原理。 现在我有它在同一排序多个图表排序的工作,但我需要每个图表在同一时间做不同的排序。 我一直在研究和试图解决这个问题,现在我只是拥有隧道视野。 我会发布我的代码,以防我的解释混乱。 我觉得这可能会使很多使用java图形的人受益,任何帮助都将不胜感激。

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

}

对于每个排序图,您需要某种模型,它应该保持每种排序的当前状态。 这可能意味着将你的int列表添加到一个单独的列表中。

您还需要某种机制,使您可以遍历每个排序算法,并告诉它移动到其算法中的下一个步骤,从而允许您控制每个排序算法何时更新,从而控制何时更新屏幕。

更新

基于OP的评论,基本上,我已经把排序算法作为一个单独的接口进行了挖掘。 每个算法都需要从这个接口扩展,但它提供了允许UI呈现排序动画的基本要求。

贝娄是基本的实现,而它是基于Swing的,如果需要的话,它将不能与AWT一起工作。

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




awt