I don't really understand why this program draws three pawns instead of one and two of which seem to have a random(probably not so random) positions. enter image description here
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class GamePanel extends JPanel implements MouseListener {
static final int SCREEN_EDGE = 800;
static final int GAME_UNITS = 64;
static final int UNIT_SIZE = 100;
final int[] x = new int[GAME_UNITS];
final int[] y = new int[GAME_UNITS];
boolean running = false;
public GamePanel() {
this.setPreferredSize(new Dimension(SCREEN_EDGE, SCREEN_EDGE));
this.setFocusable(true);
this.addKeyListener(new MyKeyAdapter());
startGame();
int[] position = {0,0};
int[] position1 = {1, 0};
new Pawn(position,-1);
}
private void startGame() {
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
draw(g);
}
public void draw(Graphics g){
int counter = 1;
for (int y = 0; y < SCREEN_EDGE/UNIT_SIZE; y++) {
// 1 == "white" 2 == "black"
int color = (y % 2 == 0) ? 1 : 2;
for (int x = 0; x < SCREEN_EDGE/UNIT_SIZE; x++) {
g.setColor(color == 1 ? new Color(239,217, 181) : new Color(180, 136,98));
g.fillRect(x*UNIT_SIZE, y*UNIT_SIZE, UNIT_SIZE, UNIT_SIZE);
color = color == 1 ? 2 : 1;
}
}
for (int i = 0; i < Figure.figures.length; i++) {
JLabel figureSprite = new JLabel(Figure.figures[i].image, JLabel.CENTER);
figureSprite.setSize(90,90);
figureSprite.setLocation(Figure.figures[i].position[0] + 5,Figure.figures[i].position[1] + 5);
this.add(figureSprite);
}
}
#Override
public void mouseClicked(MouseEvent e) {
}
#Override
public void mousePressed(MouseEvent e) {
}
#Override
public void mouseReleased(MouseEvent e) {
}
#Override
public void mouseEntered(MouseEvent e) {
}
#Override
public void mouseExited(MouseEvent e) {
}
public class MyKeyAdapter extends KeyAdapter {
#Override
public void keyPressed(KeyEvent e) {
}
}
}
import javax.swing.*;
public abstract class Figure{
protected int value;
protected ImageIcon image;
protected int[][] possibleMoves;
public int[] position;
// white = -1 black = 1
protected int whiteOrBlack;
protected static int figureCount = 1;
// int[figureCount][0 = x][1 = y][2 = color]
public static Figure[] figures = new Figure[figureCount];
public Figure(int value, int[] position, int[][] possibleMoves , int whiteOrBlack) {
this.value = value;
this.position = position;
this.possibleMoves = possibleMoves;
this.whiteOrBlack = whiteOrBlack;
Figure[] oldFigures = figures;
figures = new Figure[figureCount];
for (int i = 0; i < oldFigures.length; i++) {
figures[i] = oldFigures[i];
}
figures[figureCount - 1] = this;
figureCount++;
}
public abstract void move(int[] coordinates);
}
import javax.swing.*;
import java.awt.*;
import java.io.*;
public class Pawn extends Figure{
public Pawn(int[] position, int whiteOrBlack) {
super(1, position, new int[3][2], whiteOrBlack);
super.image = new ImageIcon(getClass().getClassLoader().getResource("graphics/" + (whiteOrBlack == -1 ? "whitePawn.png" : "blackPawn.png")));
Image newImage = super.image.getImage().getScaledInstance(90,90, Image.SCALE_AREA_AVERAGING);
super.image = new ImageIcon(newImage);
}
public void checkMoves(){
for (int i = 0; i < figures.length; i++) {
if((position[0] - 1) == figures[i].position[0] && (position[1] + this.whiteOrBlack) == figures[i].position[1] && figures[i].whiteOrBlack != this.whiteOrBlack) {
possibleMoves[0][0] = position[0] - 1;
possibleMoves[0][1] = position[1] + this.whiteOrBlack;
}else possibleMoves[0] = new int[2];
if((position[0]) != figures[i].position[0] && (position[1]) != figures[i].position[1]){
possibleMoves[1][0] = position[0];
possibleMoves[1][1] = position[1] + 1;
}else possibleMoves[1] = new int[2];
if((position[0] + 1) == figures[i].position[0] && (position[1] + this.whiteOrBlack) == figures[i].position[1] && figures[i].whiteOrBlack != this.whiteOrBlack) {
possibleMoves[2][0] = position[0] + 1;
possibleMoves[2][1] = position[1] + this.whiteOrBlack;
}else possibleMoves[2] = new int[2];
}
}
#Override
public void move(int[] coordinates) {
}
}
import javax.swing.*;
public class GameFrame extends JFrame {
public GameFrame(){
this.add(new GamePanel());
this.setTitle("Chess");
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.pack();
this.setResizable(false);
this.setVisible(true);
this.setLocationRelativeTo(null);
}
}
public class ChessGame {
public static void main(String[] args) {
new GameFrame();
}
}
I tried few thing like changing JLabel to BufferedImage but it would've generate other problems down the line like not being able to use MouseListener so i feel stuck. I would love to know why this code generates 3 textures too.
It looks like you are adding FigureSprites from within the drawComponent() method. The more often you draw the window, the more figures you have to draw.
Instead within drawComponent() just draw the current state but do not modify it. Adding figures has to come from somewhere else. For example, you could create the necessary pawns in the constructor. Or in extra methods that might get triggered based on user input.
In case you modify the GamePanel's state enough so that it should get painted freshly, just invoke repaint(). Swing will mark this component for repainting and decide on it's own when to run the paint() method, which in turn will run paintComponent().
I am making a basic platformer game and I need to make it so that every time you jump all the platforms that are below where you jumped disappear and every platform above moves down. It is still in development so just ignore some of the things that are commented out and the messy mode.
Basically, my problem is that when I try to clear all the platforms below the one that you clicked it works fine using this code:
for(int i = 0; i < platforms.length; i++) {
if(platforms[i] == null) {
continue;
}
if(parameters[i][1] > y) {
platforms[i].setVisible(false);
}
}
However later when I try to use .setvisible(true) on the platform that you clicked it doesn't work. Here is the full code:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.math.*;
import java.util.*;
public class Main implements ActionListener {
static JFrame frame;
static JPanel panel;
//static JLabel title;
//static JLabel expl;
static JButton[] platforms;
static Random random;
static boolean playing;
static int[][] parameters;
static int platformsMade;
static int clicked;
static int preClicked;
static int score;
static int lives;
static int standing;
static int speed;
static double gravity;
static int jump;
static String action;
public Main(int seed) throws Exception {
frame = new JFrame("Snakes 'n' Adders");
panel = new JPanel(null);
//title = new JLabel("Snakes 'n' Adders", SwingConstants.CENTER);
//expl = new JLabel("");
platforms = new JButton[100000];
random = new Random();
parameters = new int[100000][5];
lives = 3;
speed = 10;
gravity = 9.81;
jump = 5;
action = "";
//panel.add(title);
//panel.add(expl);
frame.add(panel);
panel.setVisible(true);
frame.setVisible(true);
frame.setSize(500, 500);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
random.setSeed(seed);
panel.setBackground(Color.CYAN);
//title.setFont(new Font("Arial", Font.PLAIN, 50));
}
public void drawPlatform(int x, int y, int w, int h, int colour) {
platforms[platformsMade] = new JButton();
platforms[platformsMade].addActionListener(this);
platforms[platformsMade].setBounds(x, y, w, h);
switch(colour) {
case 0:
platforms[platformsMade].setBackground(Color.BLUE);
break;
case 1:
platforms[platformsMade].setBackground(Color.GREEN);
break;
case 2:
platforms[platformsMade].setBackground(Color.RED);
break;
case 3:
platforms[platformsMade].setBackground(Color.ORANGE);
break;
case 4:
platforms[platformsMade].setBackground(Color.GRAY);
break;
}
parameters[platformsMade][0] = x;
parameters[platformsMade][1] = y;
parameters[platformsMade][2] = w;
parameters[platformsMade][3] = h;
parameters[platformsMade][4] = colour;
panel.add(platforms[platformsMade]);
platforms[platformsMade].setVisible(true);
panel.repaint();
platformsMade++;
}
public void movePlatforms(int distance, int i) {
if(platforms[i] == null) {
NullPointerException end = new NullPointerException();
throw end;
}
//this.drawPlatform(parameters[i][0], parameters[i][1] + distance, parameters[i][2], parameters[i][3], parameters[i][4]);
//platforms[i].setVisible(false);
platforms[i].setBounds(parameters[i][0], parameters[i][1] + distance, parameters[i][2], parameters[i][3]);
parameters[i][1] = parameters[i][1] + distance;
}
#Override
public void actionPerformed(ActionEvent event) {
preClicked = clicked;
for(int i = 0; i < platforms.length; i++) {
if(event.getSource() == platforms[i]) {
clicked = i;
break;
}
}
int y = parameters[clicked][1];
for(int i = 0; i < platforms.length; i++) {
if(platforms[i] == null) {
continue;
}
if(parameters[i][1] > y) {
platforms[i].setVisible(false);
}
else {
this.movePlatforms(150, i);
}
this.movePlatforms(150, clicked);
}
for(int i = 0; i <= random.nextInt(2); i++) {
this.drawPlatform(random.nextInt(500), random.nextInt(500), 50, 50, random.nextInt(4));
}
/*for(int i = 0; i < platforms.length; i++) {
if(platforms[i] == null) {
continue;
}
if(platforms[i].getY() > frame.getY() - platforms[i].getHeight()) {
platforms[i].setVisible(false);
}
}*/
platforms[clicked].addActionListener(this);
platforms[clicked].setVisible(true);
standing = clicked;
for(int i = 0; i < platforms.length; i++) {
if(platforms[i] == null) {
continue;
}
if(clicked == i) {
platforms[i].setText("|");
}
else {
platforms[i].setText("");
}
}
}
public static void main(String[] args) throws Exception {
Main sna = new Main(7845);
//title.setVisible(true);
//expl.setVisible(false);
//Thread.sleep(5000);
//title.setVisible(false);
//expl.setVisible(true);
//Thread.sleep(40000);
for(int i = 0; i < 3; i++) {
sna.drawPlatform(random.nextInt(500), random.nextInt(500), 50, 50, random.nextInt(4));
}
int ticks = 0;
platforms[standing].setText("|");
}
}
http://www.youtube.com/watch?v=M0cNsmjK33E
I want to develop something similar to the link above using Java Swing. I have the sorting method and did while repaint but when I triggered the sorting, instead of showing the bars slowly sorting itself, it freezes and then unfreezes when the array has been fully sorted.
How do I fix this?
Edit: sorry forgot about the codes. its a very simple gui. and another class for sorting which sorts the whole array
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) {
}
}
}
Note: I started writing this before the question was deleted
Most likely your using some looping mechanism and praying that each iteration, the ui with be updated. That's a wrong assumption. The UI will not be update until the loop is finished. What you are doing is what we refer to as blocking the Event Dispatch Thread(EDT)
See How to use a Swing Timer. Make "iterative" updates in the ActionListener call back. For instance, if you want to animate a sorting algorithm, you need to determine what needs to be updated per "iteration" of the timer callback. Then each iteration repaint the ui.
So your Timer timer could look something like
Timer timer = new Timer(40, new ActionListener(){
#Override
public void actionPerformed(ActionEvent e) {
if (sortingIsDone()) {
((Timer)e.getSource()).stop();
} else {
sortOnlyOneItem();
}
repaint();
}
});
Your sortOnlyOneItem method should only, well, perform a sort for just one item. And have some sort of flag to check if the sorting is done, then stop the timer.
Other notes:
You should be calling super.paintComponent in the paintComponent method, if you aren't going to paint the background yourself. Generally I always do though.
Here's a complete example. I'm glad you figured it out on your own. I was working on this example before I saw that you got it.
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);
}
});
}
}
So I have been coding this little UI for a while and for some reason the repaint() method seems to cause the image generated on the screen to flicker and flash. Is there a way to prevent this?
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.*;
import java.util.Timer;
public class userInterfaceSimple extends JFrame implements ActionListener
{
static ArrayList<Creature> list = new ArrayList<Creature>();
static JButton next = new JButton("Begin");
static Timer timer = new Timer();
static JFrame frame = new JFrame();
final static JPanel pane = new JPanel();
public static void main(String[] args)
{
new userInterfaceSimple();
}
public userInterfaceSimple()
{
super("Toy Planet: Life, a Simulation");
setSize(1000,1000);
setVisible(true);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLayout(new BorderLayout());
add(pane, BorderLayout.CENTER);
next.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
if(next.getText().equals("Begin"))
{
next.setText("Stop");
timer.scheduleAtFixedRate(new TimerTask()
{
#Override
public void run()
{
checkRules();
repaint();
}
}, 250, 250);
}
else
{
next.setText("Begin");
timer.cancel();
timer = new Timer();
}
}
});
add(next, BorderLayout.SOUTH);
for(int j = 0; j < 3; j ++)
{
Creature orgArc = new Creature();
for(int i = 0; i < 20; i++)
{
list.add(new Creature(orgArc.gene));
}
}
sortList();
}
public void paint(Graphics g)
{
super.paint(g);
for(int i = 0; i < list.size(); i++)
{
g.setColor(list.get(i).getColor());
int size = list.get(i).getSize();
g.fillOval(list.get(i).getX() - size/2, list.get(i).getY() - size/2,size,size);
}
}
public static void checkRules()
{
int size = list.size();
for(int i = 0; i < size; i++)
{
try
{
for(int j = 0; j < size; j++)
{
boolean alreadyMoved = false;
if(!(list.get(i)).equals(list.get(j)))
{
int x = list.get(j).getX() - (list.get(i)).getX();
int y = list.get(j).getY() - (list.get(i)).getY();
double z = Math.sqrt(x*x + y*y);
//Passive Interaction Rules
//Sight Check
if(list.get(j).getSense() > z)
{
list.get(j).moveTo(list.get(i));
alreadyMoved = true;
}
if(z <= 1.5)
{
//Active Interaction Rules
//Breeding Check
if(list.get(j).isCompatible(list.get(i)))
{
list.add(list.get(j).breed(list.get(i)));
sortList();
}
//Eating Check
else if(list.get(j).getAggro() > 15 || list.get(j).getDiet() > 3)
{
list.get(j).eat(list.get(i));
}
}
}
//If no checks fire then move randomly
if(alreadyMoved == false)
{
Organism temp = new Organism();
list.get(j).moveTo(temp);
}
}
//Hunger Check
list.get(i).hungerCheck();
}
catch(Exception e)
{
}
list.get(i).validate();
size = size - validateList();
}
/*for(int i = 0; i < list.size(); i ++) //for debugging.
{
System.out.println(list.get(i).getInfo());
}
System.out.println("----");*/
}
public static int getClosestCreature(Organism org)
{
int x,y;
double z;
double tempZ = 100000;
int closest = 0;
for(int i = 0; i < list.size(); i++)
{
if(!(list.get(i)).equals(org))
{
x = org.getX() - (list.get(i)).getX();
y = org.getY() - (list.get(i)).getY();
z = Math.sqrt(x*x + y*y);
if(z < tempZ)
{
closest = i;
tempZ = z;
}
}
}
return (closest);
}
public static int validateList()
{
int netLoss = 0;
for(int i = 0; i < list.size(); i++)
{
if((list.get(i)).getAlive() == false)
{
list.remove(i);
netLoss = netLoss + 1;
}
}
return netLoss;
}
public static void sortList()
{
Creature temp;
for(int i = 0; i < list.size(); i ++)
{
for(int j = 1; j < list.size() - i; j++)
{
if(list.get(j - 1).getSpeed() > list.get(j).getSpeed())
{
temp = list.get(j - 1);
list.set(j - 1, list.get(j));
list.set(j, temp);
}
}
}
}
#Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
}
}
Thanks for you help!
Yes, it is simple: Double Buffering should fix it. For more reference, visit http://docs.oracle.com/javase/tutorial/extra/fullscreen/doublebuf.html
First you should create private BufferedImage bufferImage;
In your public void paint(Graphics g) you should paint stuff into this bufferImage, and then, when bufferImage is filled, paint it g.drawImage(bufferImage, 0, 0, null);
public void paint(Graphics g) {
Graphics2D gr = bufferImage.createGraphics();
for(int i = 0; i < list.size(); i++)
{
gr.setColor(list.get(i).getColor());
int size = list.get(i).getSize();
gr.fillOval(list.get(i).getX() - size/2, list.get(i).getY() - size/2,size,size);
}
super(g);
g.drawImage(bufferImage, 0, 0, null);
}
Not compiled, but something like this should work.
It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 9 years ago.
Okay so I have been working on this code for awhile that shows how the sorting algorithms work. Right now I have it working where it sorts multiple graphs with the same sort but I need each graph to do a different sort at the same time. I have been researching and trying to solve this for days and now I just have tunnel vision. I'll post my code in case my explanation was confusing. I feel like this could benefit a lot of people working with java graphics and any help would be appreciated.
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;
}
}
}
For each sort graph you need some kind of model, which should hold the current state of each sort. This would probably mean adding your list of ints to a separate list per sort.
You would also need some kind of mechanism that would allow you to loop through each sort algorithm and tell it to move to the next step in its algorithm, thus allowing you to control when each sort algorithm update and therefore control when the screen is updated.
Updated
Based on a comment from the OP, basically, I've ripped out the sort algorithm as a separate interface. Each algorithm would need to extend from this interface, but it provides the basic requirements to allow the UI to render the sort animation.
Bellow is basic implementation, while it's based on Swing, if required, it wouldn't be a stretch to get it to work with 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();
}
}
}
Example using the source array
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();
}
}
}
Example Insertion Sorter
This is an example of using a Thread as the primary sort engine instead of a 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);
}
});
}
}
}