-1

I have been trying to make a bubble sort visualization in python using tkinter, but it does not work. When I put in only a few bars, nothing happens, but if try it with lots of bars, they are moving, seemingly as they should be (at first, at least). My question is, is there a mistake in my logic that I do not see, or is it just tkinter? I am starting to think the latter. Thanks in advance. Here's my code:

import tkinter
import time
import random

width = 800
height = 800
canvas = tkinter.Canvas(height=height, width=width, background='black')
canvas.pack()

thickness = 20

values = [random.randrange(height) for i in range(width//thickness)]

cc = {}

for value in values:
    cc[value] = 0

print(values)

x1 = 0
for value in values:
    canvas.create_rectangle(x1,800, x1+thickness,value, fill='white', tag=value)
    cc[value] = x1
    x1 += thickness

for i in range(len(values)):
    for j in range(len(values)-i-1):
        if values[j] > values[j+1]:
            values[j], values[j+1] = values[j+1], values[j]
            canvas.move(values[j], cc[values[j+1]] - cc[values[j]], 0)
            canvas.move(values[j+1], cc[values[j]]- cc[values[j+1]], 0)
            cc[values[j]] += (cc[values[j+1]]- cc[values[j]])
            cc[values[j+1]] += (cc[values[j]]- cc[values[j+1]])
            canvas.update()
            canvas.after(50)
            canvas.update()
        else:
            canvas.after(5)

canvas.mainloop()

print(values)
Jeff
  • 1
  • 1
  • 1
  • I would suggest `cc` as a list of rectangles. Then you don't need to move the rectangles and just update their heights based on the values at their position after swapping values. – acw1668 Mar 31 '20 at 02:15
  • First you have to understand [Event-driven programming](https://stackoverflow.com/a/9343402/7414759) and [how to use after method?](https://stackoverflow.com/questions/25753632) – stovfl Mar 31 '20 at 09:13
  • Thank you, I have looked into that, but could you elaborate on why exactly it doesn't work? I think I'm using the after method the right way, they mention in the documentation that it can also be used as a simple time.sleep method, and that was my intention. And I also don't see a simple way of implementing the moving of rectangles using a function in order to make it more event-driven, and that is why I posed the question in the first place. You cannot understand why event-driven programming with tkinter works if you don't understand why this code doesn't. – Jeff Mar 31 '20 at 12:48

1 Answers1

0

Using tag=value in create_rectangle() to identify the rectangle item may has issue if more than one items in values have same value.

I would use list to save the rectangle items instead and update their heights during sorting based on the value in the same position in values:

import tkinter as tk
import random

width = 800
height = 800
thickness = 20

# generate values
values = [random.randrange(10, height) for i in range(width//thickness)]
print(values) # initial sequence

root = tk.Tk()

canvas = tk.Canvas(root, height=height, width=width, background='black')
canvas.pack()

# create the bars
cc = []  # hold the bar items (canvas rectangle item)
for i, value in enumerate(values):
    x = i * thickness
    item = canvas.create_rectangle(x, height, x+thickness, height-value, fill='white')
    cc.append(item)

def swap_items(a, b):
    values[a], values[b] = values[b], values[a]
    # update the bar height at positons a and b
    canvas.coords(cc[a], (a*thickness, height, (a+1)*thickness, height-values[a]))
    canvas.coords(cc[b], (b*thickness, height, (b+1)*thickness, height-values[b]))

for i in range(len(values)):
    for j in range(len(values)-i-1):
        if values[j] > values[j+1]:
            swap_items(j, j+1)
            canvas.update()
            canvas.after(50)
        else:
            canvas.after(5)
print(values) # sorted sequence

root.mainloop()
acw1668
  • 40,144
  • 5
  • 22
  • 34
  • Thank you very much! I didn't know you could use canvas.coords that way. It has been extremely helpful, because now I know that tkinter works as intended after all. – Jeff Apr 02 '20 at 08:40