Zayza
Zayza

Reputation: 11

Bubblesort visualization in tkinter

I can't figure out how can I finish one simple program written in Python. Program basically generates array of ten random numbers and then sorts them using bubblesort algorithm. Whole shorting process should be shown on screen - such as this one

enter image description here

My current code is this:

import tkinter
import random
canvas = tkinter.Canvas(bg='white',width='800',height='400')
canvas.pack()

c = []
for i in range(0,10):
    c=c+[random.randrange(10)]
print(c)
print('Zoradenie...', c)

def sort(c):
    x=300
    for i in range(0,10):
        for j in range(0,len(c)-1-1):
            if c[j+1]<c[j]:
                c[j+1],c[j]=c[j],c[j+1]
                canvas.create_text(300,80,text=c[j],fill='Red')
            x+=25
            canvas.update()
            canvas.after(1000)
            print(c)              
    return c
sort(c)

But I can't figure out how to show numbers on screen. Any ideas?

Upvotes: 1

Views: 1363

Answers (1)

Terry Jan Reedy
Terry Jan Reedy

Reputation: 19174

To display the digits on the canvas, you must create a text item for each digit. See the end of my code. The harder part is moving the digits. One way is to delete and recreate; the other is to move. I choose the latter.

The hardest part, perhaps, is the time delays. If one uses mainloop, one should use after rather than time.sleep (which blocks the looping) and not use for-loops for animation. The problem is that the function (here sort) that naturally contains for-loops must be broken into pieces whose joint operation may be hard to understand. If one is running just one function and does not care about user interaction (for instance, a pause button), one can use time.sleep and update. I have done so here to make what is going on clearer.

from random import randrange
from time import sleep
import tkinter as tk

root = tk.Tk()
canvas = tk.Canvas(root, bg='white', width='800', height='400')
canvas.pack()

ndigits = 10
digits = [randrange(10) for _ in range(ndigits)]
tdelta1, tdelta2 = .8, .2
xstart = 300
xdelta = 25
y = 80

def color(i, swap):
    "Temporarily color digits i and i+i according to swap needed."
    x = xstart + xdelta * i
    dcolor = 'Red' if swap else 'green'
    canvas.itemconfigure(items[i], fill=dcolor)
    canvas.itemconfigure(items[i+1],fill=dcolor)
    canvas.update()
    sleep(tdelta1)
    canvas.itemconfigure(items[i], fill='Black')
    canvas.itemconfigure(items[i+1], fill='Black')
    canvas.update()
    sleep(tdelta2)

def swap(i):
    digits[i], digits[i+1] = digits[i+1], digits[i]
    canvas.move(items[i], xdelta, 0)
    canvas.move(items[i+1], -xdelta, 0)
    items[i], items[i+1] = items[i+1], items[i]


def bubsort():
    "Sort digits and animate."
    for stop in reversed(range(1, ndigits)):
        # stop = index of position whose entry will be determined.
        for i in range(stop):
            swap_needed = digits[i] > digits[i+1]
            color(i, swap_needed)
            if swap_needed:
                swap(i)
                color(i, False)

# Create display items and pause.
items = [canvas.create_text(xstart + xdelta*i, y, text=str(digit))
         for i, digit in enumerate(digits)]
canvas.update()
sleep(tdelta1)

bubsort()

This code makes it fairly easy to replace the text digit display with, for instance, a colored bar display. To develop this further, I would define a class of items combining int values and display items as attributes. There would them be only one array of combined items. With comparison methods defines, the array could be passed to any sort function.

Upvotes: 1

Related Questions