|
5 | 5 |
|
6 | 6 | root = Tk()
|
7 | 7 | root.title("Array sort visualizer")
|
8 | | -root.maxsize(900, 600) |
| 8 | +root.geometry("950x600") |
9 | 9 | root.config(bg='black')
|
10 | 10 |
|
11 | | -data = [] |
12 | | - |
13 | 11 | # variables
|
14 | 12 | selected_alg = StringVar()
|
| 13 | +data = [] |
| 14 | +MIN_BAR = 2 |
| 15 | +MAX_BAR = 2**5 |
| 16 | + |
| 17 | +def initArrayData(maxBar): |
| 18 | + global data |
| 19 | + |
| 20 | + data = [] |
| 21 | + for x in range(maxBar): |
| 22 | + data.append(x+1) |
15 | 23 |
|
16 | 24 | def drawData(data, colorArray):
|
17 | | - canvas.delete('all') |
18 | | - c_height = 300 |
19 | | - c_widtht = 600 |
20 | | - x_widtht = c_widtht / (len(data) +1) |
21 | | - offset = 30 |
22 | | - spacing = 3 |
| 25 | + C_BODY_ANIMATION.delete('all') |
| 26 | + c_height = 460 |
| 27 | + c_widtht = 860 |
| 28 | + x_widtht = c_widtht / len(data) |
| 29 | + offset = 0 |
| 30 | + spacing = 0 |
23 | 31 | normalizeData = [i / max(data) for i in data]
|
24 | 32 | for i, height in enumerate(normalizeData):
|
25 | 33 | # top left
|
26 | 34 | x0 = i * x_widtht + offset + spacing
|
27 | | - y0 = c_height - height * 260 |
| 35 | + y0 = c_height - height * 440 |
28 | 36 | # bottom right
|
29 | 37 | x1 = (i + 1) * x_widtht + offset
|
30 | 38 | y1 = c_height
|
31 | | - canvas.create_rectangle(x0, y0, x1, y1, fill=colorArray[i]) |
32 | | - canvas.create_text(x0 + 2, y0, anchor=SW, text=str(data[i])) |
| 39 | + C_BODY_ANIMATION.create_rectangle(x0, y0, x1, y1, fill=colorArray[i], outline="") |
| 40 | + C_BODY_ANIMATION.create_text(x0 + (x_widtht/2) -6, y0, anchor=SW, text=str(data[i])) |
33 | 41 |
|
34 | 42 | root.update_idletasks()
|
35 | 43 |
|
36 | 44 |
|
37 | 45 | def Generate():
|
38 | 46 | global data
|
| 47 | + global MAX_BAR |
39 | 48 |
|
40 | | - minVal = int(minEntry.get()) |
41 | | - maxVal = int(maxEntry.get()) |
42 | | - size = int(sizeEntry.get()) |
43 | | - |
44 | | - data = [] |
45 | | - |
46 | | - for _ in range(size): |
47 | | - data.append(random.randrange(minVal, maxVal + 1)) |
| 49 | + initArrayData(MAX_BAR) |
48 | 50 |
|
| 51 | + for x in range(MAX_BAR): |
| 52 | + rng = random.randrange(0, MAX_BAR) |
| 53 | + data[x], data[rng] = data[rng], data[x] |
49 | 54 | drawData(data, ['steelblue' for x in range(len(data))])
|
50 | 55 |
|
51 | | - |
52 | 56 | def StartAlgorithm():
|
53 | 57 | global data
|
54 | | - bubble_sort(data, drawData, speedScale.get()) |
55 | | - |
56 | | - |
57 | | -# frame / base layout |
58 | | -UI_frame = Frame(root, width=600, height=200, bg='grey') |
59 | | -UI_frame.grid(row=0, column=0, padx=10, pady=5) |
60 | | - |
61 | | -canvas = Canvas(root, width=600, height=300, bg='white') |
62 | | -canvas.grid(row=1, column=0, padx=10, pady=5) |
63 | | - |
64 | | -# User interface area |
65 | | -# Row[0] |
66 | | -Label(UI_frame, text='Algoritmos: ', bg='grey',).grid(row=0, column=0, padx=5, pady=5, sticky=W) |
67 | | -algMenu = ttk.Combobox(UI_frame, textvariable=selected_alg, values=['Bubble Sort', 'Merge Sort']) |
68 | | -algMenu.grid(row=0, column=1, padx=5, pady=5) |
69 | | -algMenu.current(0) |
| 58 | + bubble_sort(data, drawData, 0.01) |
70 | 59 |
|
71 | | -speedScale = Scale(UI_frame, from_=0.1, to=2.0, length=200, digits=2, resolution=0.1, orient=HORIZONTAL, label="Select Speed [s]") |
72 | | -speedScale.grid(row=0, column=2, padx=5, pady=5) |
73 | | -Button(UI_frame, text='Start', command=StartAlgorithm, bg='red').grid(row=0, column=3, padx=5, pady=5) |
74 | | - |
75 | | -# Row[1] |
76 | | -sizeEntry = Scale(UI_frame, from_=3, to=25, resolution=1, orient=HORIZONTAL, label='Data size') |
77 | | -sizeEntry.grid(row=1, column=0, padx=5, pady=5) |
78 | | - |
79 | | -minEntry = Scale(UI_frame, from_=0, to=10, resolution=1, orient=HORIZONTAL, label='Min value') |
80 | | -minEntry.grid(row=1, column=1, padx=5, pady=5) |
81 | | - |
82 | | -maxEntry = Scale(UI_frame, from_=10, to=100, resolution=1, orient=HORIZONTAL, label='Max value') |
83 | | -maxEntry.grid(row=1, column=2, padx=5, pady=5) |
| 60 | +def initGenerate(): |
| 61 | + global data |
| 62 | + initArrayData(MAX_BAR) |
| 63 | + drawData(data, ['steelblue' for x in range(len(data))]) |
84 | 64 |
|
85 | | -Button(UI_frame, text='Generate', command=Generate, bg='white').grid(row=1, column=3, padx=5, pady=5) |
| 65 | +def openSettings(): |
| 66 | + settingWindows = Toplevel() |
| 67 | + settingWindows.grab_set() # Mantiene el foco de la ventana hasta que se cierre y devuelve la interacción con la ventana principal, el root en este caso. |
| 68 | + settingWindows.focus_set() # Mantiene el foco cuando se abre la ventana. |
| 69 | + settingWindows.title("Opciones") |
| 70 | + settingWindows.geometry("600x400") |
| 71 | + settingWindows.config(bg='white') |
| 72 | + |
| 73 | + sizeEntry = Scale(settingWindows, from_=3, to=25, resolution=1, orient=HORIZONTAL, label='Data size') |
| 74 | + sizeEntry.grid(row=1, column=0, padx=5, pady=5) |
| 75 | + |
| 76 | + minEntry = Scale(settingWindows, from_=0, to=10, resolution=1, orient=HORIZONTAL, label='Min value') |
| 77 | + minEntry.grid(row=1, column=1, padx=5, pady=5) |
| 78 | + |
| 79 | + maxEntry = Scale(settingWindows, from_=10, to=100, resolution=1, orient=HORIZONTAL, label='Max value') |
| 80 | + maxEntry.grid(row=1, column=2, padx=5, pady=5) |
| 81 | + |
| 82 | + speedScale = Scale(settingWindows, from_=0.1, to=2.0, length=200, digits=2, resolution=0.1, orient=HORIZONTAL, label="Select Speed [s]") |
| 83 | + speedScale.grid(row=0, column=2, padx=5, pady=5) |
| 84 | + |
| 85 | +"""Menu principal superior""" |
| 86 | +C_MENU = Canvas(root, width=950, height=50, bg='#f0f0f0', highlightthickness=0) |
| 87 | +C_MENU.grid(row=0, column=0) |
| 88 | +C_MENU.grid_propagate(False) |
| 89 | +C_MENU.grid_rowconfigure(0, weight=1) |
| 90 | +C_MENU.grid_columnconfigure(0, weight=1) |
| 91 | + |
| 92 | +# Frame para almacenar los botones de accion del programa |
| 93 | +F_MENU_BTNS = Frame(C_MENU, width=950, height=50, bg='#f0f0f0') |
| 94 | +F_MENU_BTNS.grid(row=0, column=0, sticky=W) |
| 95 | + |
| 96 | +# Col[0] - Button Play |
| 97 | +photoPlayButton = PhotoImage(file = r"./img/play-button.png") |
| 98 | +Button(F_MENU_BTNS, text='play', width=26, height=26, bg="#f0f0f0", border=0, activebackground="#ffffff", command=StartAlgorithm, image=photoPlayButton).grid(row=0, column=0, padx=5, pady=5) |
| 99 | +# Col[1] - Button restart |
| 100 | +photoRefresh = PhotoImage(file = r"./img/refresh.png") |
| 101 | +Button(F_MENU_BTNS, text='restart', width=26, height=26, bg="#f0f0f0", border=0, activebackground="#ffffff", command=Generate, image=photoRefresh).grid(row=0, column=1, padx=5, pady=5) |
| 102 | +# Col[2] - Button settings |
| 103 | +# photoSettings = PhotoImage(file = r"./img/settings.png") |
| 104 | +# Button(F_MENU_BTNS, text='settings', width=26, height=26, bg="#f0f0f0", border=0, activebackground="#ffffff", command=openSettings, image=photoSettings).grid(row=0, column=2, padx=5, pady=5) |
| 105 | + |
| 106 | +"""Canvas para la representacion de las barras del array y animaciones""" |
| 107 | +C_BODY = Canvas(root, width=950, height=550, bg='#ffffff', highlightthickness=0) |
| 108 | +C_BODY.grid(row=1, column=0) |
| 109 | +C_BODY.grid_propagate(False) |
| 110 | + |
| 111 | +# Canvas que rodea el Canvas principal con la animacion del algoritmo Sort |
| 112 | +C_BODY_BORDER = Canvas(C_BODY, width=900, height=500, bg='#ffffff', bd=-2) |
| 113 | +C_BODY_BORDER.create_rectangle(0, 0, 900, 500, width=2) |
| 114 | +C_BODY_BORDER.grid(row=0, column=0, padx=20, pady=20) |
| 115 | + |
| 116 | +# Canvas principal donde se representa el array y su animacion de ordenacion |
| 117 | +C_BODY_ANIMATION = Canvas(C_BODY, width=860, height=460, bg='#ffffff', bd=-2) |
| 118 | +C_BODY_ANIMATION.grid(row=0, column=0, padx=20, pady=20) |
| 119 | + |
| 120 | +# Iniciado de animaciones al iniciar el programa |
| 121 | +initGenerate() |
86 | 122 |
|
87 | 123 | # Main loop
|
88 | 124 | root.mainloop()
|
0 commit comments