Bubble sort animation
Another approach might be to use a SwingWorker.
The SwingWorker creates runs in its own Thread and allows you to "publish" intermittent results to be painted.
The key to the approach below is that a copy of the data is passed to the SwingWorker. This allows the worker to sort the data while the data is being repainted so you don't have to worry about the data in the array being in an inconsistent state.
After each iteration of the looping code the new state of the array is updated so it can be painted.
This allows you to easily move the sorting logic into the SwingWorker without refactoring.
import java.awt.*;
import java.awt.event.*;
import java.util.Arrays;
import java.util.List;
import javax.swing.*;
import javax.swing.Timer;
public class BubbleSortWorker extends JPanel
{
private final static int BAR_WIDTH = 30;
private final static int BAR_HEIGHT_MAX = 400;
private int[]items;
private boolean everySwap;
public BubbleSortWorker(int[] items, boolean everySwap)
{
this.items = items;
this.everySwap = everySwap;
}
public void setItems(int[] items)
{
this.items = items;
repaint();
}
public void sort()
{
new SortWorker(items).execute();
}
@Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
for (int i = 0; i < items.length; i++)
{
int x = i * BAR_WIDTH;
int y = getHeight() - items[i];
g.setColor( Color.RED );
g.fillRect(x, y, BAR_WIDTH, items[i]);
g.setColor( Color.BLUE );
g.drawString("" + items[i], x, y);
}
}
@Override
public Dimension getPreferredSize()
{
return new Dimension(items.length * BAR_WIDTH, BAR_HEIGHT_MAX + 20);
}
class SortWorker extends SwingWorker<Void, int[]>
{
private int[] items;
public SortWorker(int[] unsortedItems)
{
items = Arrays.copyOf(unsortedItems, unsortedItems.length);
}
@Override
protected Void doInBackground()
{
int n = items.length;
int temp = 0;
for (int i = 0; i < n; i++)
{
for (int j = 1; j < (n - i); j++)
{
if (items[j-1] > items[j])
{
temp = items[j - 1];
items[j - 1] = items[j];
items[j] = temp;
// Update after every swap is done
if (everySwap)
{
publish( Arrays.copyOf(items, items.length) );
try { Thread.sleep(100); } catch (Exception e) {}
}
}
}
// Update once per iteration
if (!everySwap)
{
publish( Arrays.copyOf(items, items.length) );
try { Thread.sleep(500); } catch (Exception e) {}
}
}
return null;
}
@Override
protected void process(List<int[]> list)
{
int[] items = list.get(list.size() - 1);
setItems( items );
}
@Override
protected void done() {}
}
public static int[]generateRandomNumbers()
{
int[] items = new int[10];
for(int i = 0; i < items.length; i++)
{
items[i] = (int)(Math.random() * BubbleSortWorker.BAR_HEIGHT_MAX);
}
return items;
}
private static void createAndShowGUI()
{
BubbleSortWorker bubbleSort = new BubbleSortWorker(BubbleSortWorker.generateRandomNumbers(), true);
JButton generate = new JButton("Generate Data");
generate.addActionListener((e) -> bubbleSort.setItems(BubbleSortWorker.generateRandomNumbers() ) );
JButton sort = new JButton("Sort Data");
sort.addActionListener((e) -> bubbleSort.sort());
JPanel bottom = new JPanel();
bottom.add( generate );
bottom.add( sort );
JFrame frame = new JFrame("SSCCE");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(bubbleSort, BorderLayout.CENTER);
frame.add(bottom, BorderLayout.PAGE_END);
frame.pack();
frame.setLocationByPlatform( true );
frame.setVisible( true );
}
public static void main(String[] args) throws Exception
{
EventQueue.invokeLater( () -> createAndShowGUI() );
}
}
Check out Worker Threads and Swing Worker for more information about SwingWorker
.
How do I correctly implement a bubble sort algorithm in python tkinter?
The biggest problem is that inside sort_two
you have if
if y2 > y1:
canvas.move(pos_0, x_10-x_00, 0)
canvas.move(pos_1, x_01-x_11, 0)
which replaces elements only if y2 > y1
but after sort_two()
you use barList
sort_two(pos_1, pos_2)
barList[rd1], barList[rd2] = barList[rd2], barList[rd1]
which always replaces elements on list.
And this way you have wrong results on screen.
You could return True/False
from sort_two()
to control when to change elements on barList
if y2 > y1:
canvas.move(pos_0, x_10-x_00, 0)
canvas.move(pos_1, x_01-x_11, 0)
return True
else:
return False
and
if sort_two(pos_1, pos_2):
barList[rd1], barList[rd2] = barList[rd2], barList[rd1]
Here finall code
I use simple calculation for replacing elements on canvas
x1, _, _, _ = canvas.coords(pos_0)
x2, _, _, _ = canvas.coords(pos_1)
diff = x1 - x2
canvas.move(pos_0, -diff, 0)
canvas.move(pos_1, +diff, 0)
I also removed
else:
break
which stop animation after every replace and it needs to click button sort
again and again - and I use
window.update()
time.sleep(0.1)
so it displays animation (slowly) to the end of sorting and I don't have to click button sort
import tkinter as tk
import random
import time
def swap_two_pos(pos_0, pos_1):
"""This does the graphical swapping of the rectangles on the canvas
by moving one rectangle to the location of the other, and vice versa
"""
x1, _, _, _ = canvas.coords(pos_0)
x2, _, _, _ = canvas.coords(pos_1)
diff = x1 - x2
canvas.move(pos_0, -diff, 0)
canvas.move(pos_1, +diff, 0)
def sort_two(pos_0, pos_1):
x1, y1, _, _ = canvas.coords(pos_0)
x2, y2, _, _ = canvas.coords(pos_1)
diff = x1 - x2
# moves each rectangle to the x position of the other; y remains unchanged
if y2 > y1:
canvas.move(pos_0, -diff, 0)
canvas.move(pos_1, +diff, 0)
return True
else:
return False
def rand_sort():
for i in range(50000):
rd1 = random.randint(0, 58)
rd2 = random.randint(0, 58)
pos_1 = barList[rd1]
pos_2 = barList[rd2]
if sort_two(pos_1, pos_2):
barList[rd1], barList[rd2] = barList[rd2], barList[rd1]
def sort ():
n = len(barList)
# Traverse through all array elements
for i in range(n):
# Last i elements are already in place
for j in range(0, n-i-1):
if sort_two(barList[j], barList[j+1]):
barList[j], barList[j+1] = barList[j+1], barList[j]
window.update()
time.sleep(0.1)
def random_swap():
"""Not a sort yet, but you have the bare bones operations
so the swap is executed
"""
for i in range(500):
rd1 = random.randint(0, 58)
rd2 = random.randint(0, 58)
pos_0 = barList[rd1]
pos_1 = barList[rd2]
swap_two_pos(pos_0, pos_1)
# it is necessary to swap the values in the list too
barList[rd1], barList[rd2] = barList[rd2], barList[rd1]
window = tk.Tk()
window.title('Sorting')
window.geometry('600x400')
# button to command the swap
tk.Button(window, text='swap', command=random_swap).pack()
tk.Button(window, text='sort', command=sort).pack()
xstart = 5
xend = 15
canvas = tk.Canvas(window, width='900', height='900')
canvas.pack()
barList = []
lengthList = []
Y = 5
for x in range(1,60):
bar = canvas.create_rectangle(xstart, Y, xend, 395, fill='red')
barList.append(bar)
xstart += 10
xend += 10
Y += 5
for bar in barList:
x = canvas.coords(bar)
length = x[3]-x[1]
lengthList.append(length)
window.mainloop()
Visualising bubble sort using chart.js
You can use the setTimeout()
method and update the labels
, dataset.data
and dataset.backgroundColor
with a certain delay each time array elements are swapped. Then you also need to invoke chart.update()
to make sure, Chart.js re-draws the updated chart on the canvas
.
Please take a look at the runnable code below and see how it works.
function bubbleSort() {
let labels = chart.data.labels;
let data = chart.data.datasets[0].data;
let colors = chart.data.datasets[0].backgroundColor;
let swapped;
let timeout = 0;
do {
swapped = false;
for (let i = 0; i < data.length; i++) {
if (data[i] > data[i + 1]) {
swap(labels, i);
swap(data, i);
swap(colors, i);
timeout += 50;
this.updateChartDelayed(labels.slice(0), data.slice(0), colors.slice(0), timeout);
swapped = true;
}
}
} while (swapped);
}
function swap(arr, i) {
let tmp = arr[i];
arr[i] = arr[i + 1];
arr[i + 1] = tmp;
}
function updateChartDelayed(labels, data, colors, timeout) {
setTimeout(() => {
chart.data.labels = labels;
chart.data.datasets[0].data = data;
chart.data.datasets[0].backgroundColor = colors;
chart.update();
}, timeout);
}
const labels = ['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'];
const chart = new Chart('myChart', {
type: 'bar',
data: {
labels: labels,
datasets: [{
data: labels.map(() => Math.random()),
backgroundColor: ['#FF6633', '#FFB399', '#FF33FF', '#FFFF99', '#00B3E6', '#E6B333', '#3366E6', '#999966', '#99FF99', '#B34D4D', '#80B300', '#809900', '#E6B3B3', '#6680B3', '#66991A', '#66664D', '#991AFF', '#E666FF', '#4DB3FF', '#1AB399', '#4D8066', '#809980', '#E6FF80', '#1AFF33', '#999933', '#FF4D4D'],
borderWidth: 1
}]
},
options: {
legend: {
display: false
},
scales: {
yAxes: [{
ticks: {
beginAtZero: true
}
}]
}
}
});
setTimeout(() => bubbleSort(), 1000);
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.4/Chart.min.js"></script>
<canvas id="myChart" height="90"></canvas>
Related Topics
Bigdecimal Equals() Versus Compareto()
How to Format a String in an Email So Outlook Will Print the Line Breaks
Removing Invalid Xml Characters from a String in Java
How to Lower Java Heap When Not in Use
How to Use Printwriter and File Classes in Java
Lambda Expression to Convert Array/List of String to Array/List of Integers
Should I Call Ugi.Checktgtandreloginfromkeytab() Before Every Action on Hadoop
How to Import Spring-Config.Xml of One Project into Spring-Config.Xml of Another Project
Dynamically Change Spring Data Source
How to Get Absolute Path to File in /Resources Folder of Your Project
Java:Parse Java Source Code, Extract Methods
Getting Java.Lang.Classnotfoundexception: Org.Apache.Commons.Logging.Logfactory Exception
How to Get a List of Ip Connected in Same Network (Subnet) Using Java
How to Validate an Xml File Using Java with an Xsd Having an Include