我正在使用tkinter使用不同条形的高度来可视化不同排序算法。我已经能够重新整理酒吧,并在得到一些帮助后对其进行排序。我现在遇到的问题是减慢条形的排序速度,因此可以看出每种算法的工作原理。这是我到目前为止的内容:
import tkinter as tk import random def swap_two_pos(pos_0, pos_1): Bar1x1, _, Bar1x2, _ = canvas.coords(pos_0) Bar2x1, _, Bar2x2, _ = canvas.coords(pos_1) canvas.move(pos_0, Bar2x1-Bar1x1, 0) canvas.move(pos_1, Bar1x2-Bar2x2, 0) def insertion_sort(): global barList global lengthList for i in range(len(lengthList)): cursor = lengthList[i] cursorBar = barList[i] pos = i while pos > 0 and lengthList[pos - 1] > cursor: lengthList[pos] = lengthList[pos - 1] barList[pos], barList[pos - 1] = barList[pos - 1], barList[pos] canvas.after(1000,swap_two_pos(barList[pos],barList[pos-1])) pos -= 1 lengthList[pos] = cursor barList[pos] = cursorBar swap_two_pos(barList[pos],cursorBar) def shuffle(): global barList global lengthList canvas.delete('all') xstart = 5 xend = 15 barList = [] lengthList = [] for x in range(1,60): randomY = random.randint(1,390) x = canvas.create_rectangle(xstart,randomY,xend,395, fill='red') barList.append(x) xstart += 10 xend += 10 for bar in barList: x = canvas.coords(bar) length = x[3]-x[1] lengthList.append(length) for i in range(len(lengthList)-1): if lengthList[i] == min(lengthList): canvas.itemconfig(barList[i], fill='blue') elif lengthList[i] == max(lengthList): canvas.itemconfig(barList[i], fill='green') window = tk.Tk() window.title('Sorting') window.geometry('600x435') canvas = tk.Canvas(window, width='600', height='400') canvas.grid(column=0,row=0, columnspan = 50) insert = tk.Button(window, text='Insertion Sort', command=insertion_sort) shuf = tk.Button(window, text='Shuffle', command=shuffle) insert.grid(column=1,row=1) shuf.grid(column=0, row=1) shuffle() window.mainloop()
如您所见,我尝试after()在插入排序函数中使用该方法,但是它所做的只是冻结窗口并使其不响应。如果没有该方法,它将无法正常工作,只是步伐不明显。
after()
利用生成器函数(关键字yield),您可以暂停代码中间循环的执行,以花时间显示已更改的画布元素,更新计算等,然后在next反复调用生成器时恢复执行,直到排序完成。
yield
next
我在代码中添加了一些注释,但是最好的方法可能是凝视它,直到您确信自己可以按预期工作为止。这是您需要了解的一种模式,因为它对构造您想要构建的动画非常有用。
import tkinter as tk import random def swap_two_pos(pos_0, pos_1): Bar1x1, _, Bar1x2, _ = canvas.coords(pos_0) Bar2x1, _, Bar2x2, _ = canvas.coords(pos_1) canvas.move(pos_0, Bar2x1-Bar1x1, 0) canvas.move(pos_1, Bar1x2-Bar2x2, 0) def _insertion_sort(): global barList global lengthList for i in range(len(lengthList)): cursor = lengthList[i] cursorBar = barList[i] pos = i while pos > 0 and lengthList[pos - 1] > cursor: lengthList[pos] = lengthList[pos - 1] barList[pos], barList[pos - 1] = barList[pos - 1], barList[pos] swap_two_pos(barList[pos],barList[pos-1]) # <-- updates the display yield # <-- suspends the execution pos -= 1 # <-- execution resumes here when next is called lengthList[pos] = cursor barList[pos] = cursorBar swap_two_pos(barList[pos],cursorBar) worker = None # <-- Not a thread in spite of the name. def insertion_sort(): # <-- commands the start of both the animation, and the sort global worker worker = _insertion_sort() animate() def animate(): # <-- commands resuming the sort once the display has been updated # controls the pace of the animation global worker if worker is not None: try: next(worker) window.after(10, animate) # <-- repeats until the sort is complete, except StopIteration: # when the generator is exhausted worker = None finally: window.after_cancel(animate) # <-- stop the callbacks def shuffle(): global barList global lengthList canvas.delete('all') xstart = 5 xend = 15 barList = [] lengthList = [] for x in range(1, 60): randomY = random.randint(1, 390) x = canvas.create_rectangle(xstart, randomY, xend, 395, fill='red') barList.append(x) xstart += 10 xend += 10 for bar in barList: x = canvas.coords(bar) length = x[3] - x[1] lengthList.append(length) for i in range(len(lengthList)-1): if lengthList[i] == min(lengthList): canvas.itemconfig(barList[i], fill='blue') elif lengthList[i] == max(lengthList): canvas.itemconfig(barList[i], fill='green') window = tk.Tk() window.title('Sorting') window.geometry('600x435') canvas = tk.Canvas(window, width='600', height='400') canvas.grid(column=0,row=0, columnspan = 50) insert = tk.Button(window, text='Insertion Sort', command=insertion_sort) shuf = tk.Button(window, text='Shuffle', command=shuffle) insert.grid(column=1,row=1) shuf.grid(column=0, row=1) shuffle() window.mainloop()