请有人帮我修复滚动条,并为第三个画布添加滚动条。 实际上我已经创建了数据结构可视化工具。面对滚动条,目前我无法滚动到第三个画布。 语言-pyhton
import tkinter as tk
from tkinter import ttk, messagebox
import matplotlib.pyplot as plt
import time
class VisualizerApp:
def __init__(self, root):
self.root = root
self.root.title("Data Structure and Sorting Algorithm")
self.root.geometry("1200x800")
# Canvas for the Main Window
self.canvas = tk.Canvas(root)
self.canvas.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
# Scrollbars for the main window
self.scroll_x = tk.Scrollbar(root, orient=tk.HORIZONTAL, command=self.canvas.xview)
self.scroll_x.pack(side=tk.BOTTOM, fill=tk.X)
self.scroll_y = tk.Scrollbar(root, orient=tk.VERTICAL, command=self.canvas.yview)
self.scroll_y.pack(side=tk.RIGHT, fill=tk.Y)
# Frame for the widgets
self.frame = tk.Frame(self.canvas)
self.canvas.create_window((0, 0), window=self.frame, anchor='nw')
# Configure Canvas scrolling
self.frame.bind("<Configure>", self.on_frame_configure)
self.canvas.config(xscrollcommand=self.scroll_x.set, yscrollcommand=self.scroll_y.set)
# Setup UI
self.setup_ui()
def setup_ui(self):
# Frame for data structure selection and visualization
self.data_frame = tk.Frame(self.frame)
self.data_frame.pack(padx=10, pady=10, fill=tk.BOTH, expand=True)
# Dropdown menus for data structures
tk.Label(self.data_frame, text="Select Data Structure:", fg="black").pack(padx=10, pady=5, anchor=tk.W)
options = ["Array", "Stack", "Linked List", "Set", "Tuple", "Dictionary"]
self.data_structure = tk.StringVar(value=options[0])
data_structure_menu = tk.OptionMenu(self.data_frame, self.data_structure, *options)
data_structure_menu.pack(padx=10, pady=5, anchor=tk.W)
# Entry for the values
tk.Label(self.data_frame, text="Enter Values (Comma Separated):", fg="black").pack(padx=10, pady=5, anchor=tk.W)
self.data_entry = tk.Entry(self.data_frame)
self.data_entry.pack(padx=10, pady=5, anchor=tk.W)
# Canvas for visualizing data structures
self.canvas_data_structure = tk.Canvas(self.data_frame, bg="white", width=1000, height=300)
self.canvas_data_structure.pack(padx=10, pady=5, fill=tk.BOTH, expand=True)
# Scrollbars for data structure canvas
self.scroll_x_data = tk.Scrollbar(self.data_frame, orient=tk.HORIZONTAL, command=self.canvas_data_structure.xview)
self.scroll_x_data.pack(side=tk.BOTTOM, fill=tk.X)
self.canvas_data_structure.config(xscrollcommand=self.scroll_x_data.set)
self.scroll_y_data = tk.Scrollbar(self.data_frame, orient=tk.VERTICAL, command=self.canvas_data_structure.yview)
self.scroll_y_data.pack(side=tk.RIGHT, fill=tk.Y)
self.canvas_data_structure.config(yscrollcommand=self.scroll_y_data.set)
# Button for visualizing data structure
self.visualize_button = tk.Button(self.data_frame, text="Visualize Data Structure", command=self.visualize_data_structure)
self.visualize_button.pack(padx=10, pady=5)
# Frame for sorting algorithm selection and visualization
self.sort_frame = tk.Frame(self.frame)
self.sort_frame.pack(padx=10, pady=10, fill=tk.BOTH, expand=True)
# Dropdown menu for sorting algorithms
tk.Label(self.sort_frame, text="Select Sorting Algorithm:", fg="black").pack(padx=10, pady=5, anchor=tk.W)
options2 = ["Bubble Sort", "Insertion Sort", "Quick Sort"]
self.sorting_algos = tk.StringVar(value=options2[0])
sorting_algorithm_menu = tk.OptionMenu(self.sort_frame, self.sorting_algos, *options2)
sorting_algorithm_menu.pack(padx=10, pady=5, anchor=tk.W)
# Button for sort and visualize
self.sort_button = tk.Button(self.sort_frame, text="Sort and Visualize", command=self.sort_and_visualize)
self.sort_button.pack(padx=10, pady=5)
# Frame and canvas for sorting visualization
self.sorting_canvas_frame = tk.Frame(self.sort_frame)
self.sorting_canvas_frame.pack(padx=10, pady=5, fill=tk.BOTH, expand=True)
self.canvas_sorting = tk.Canvas(self.sorting_canvas_frame, bg="white", width=1000, height=300)
self.canvas_sorting.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
# Scrollbars for sorting canvas
self.scroll_x_sort = tk.Scrollbar(self.sorting_canvas_frame, orient=tk.HORIZONTAL, command=self.canvas_sorting.xview)
self.scroll_x_sort.pack(side=tk.BOTTOM, fill=tk.X)
self.canvas_sorting.config(xscrollcommand=self.scroll_x_sort.set)
self.scroll_y_sort = tk.Scrollbar(self.sorting_canvas_frame, orient=tk.VERTICAL, command=self.canvas_sorting.yview)
self.scroll_y_sort.pack(side=tk.RIGHT, fill=tk.Y)
self.canvas_sorting.config(yscrollcommand=self.scroll_y_sort.set)
# Text area for the explanation
self.explanation_frame = tk.Frame(self.frame)
self.explanation_frame.pack(padx=10, pady=10, fill=tk.BOTH, expand=True)
self.explanation_text = tk.Text(self.explanation_frame, height=10, width=100)
self.explanation_text.pack(padx=10, pady=5, fill=tk.BOTH, expand=True)
def on_frame_configure(self, event):
self.canvas.config(scrollregion=self.canvas.bbox("all"))
self.canvas_data_structure.config(scrollregion=self.canvas_data_structure.bbox("all"))
self.canvas_sorting.config(scrollregion=self.canvas_sorting.bbox("all"))
def visualize_data_structure(self):
data_type = self.data_structure.get()
values = self.data_entry.get()
if not data_type or not values:
messagebox.showerror("Input Error", "Please select a data structure and enter values")
return
try:
self.data = list(map(int, values.split(',')))
except ValueError:
messagebox.showerror("Input Error", "Please enter valid integer values.")
return
if data_type == "Array" or data_type == "Tuple":
self.draw_array(self.data, self.canvas_data_structure)
elif data_type == "Stack":
self.draw_stack(self.data, self.canvas_data_structure)
elif data_type == "Linked List":
self.draw_linked_list(self.data, self.canvas_data_structure)
elif data_type == "Set":
self.draw_set(set(self.data), self.canvas_data_structure)
elif data_type == "Dictionary":
self.draw_dictionary({i: val for i, val in enumerate(self.data)}, self.canvas_data_structure)
def draw_array(self, data, canvas, color_array=None):
canvas.delete("all")
canvas_height = 180
canvas_width = max(800, len(data) * 100)
bar_width = canvas_width / (len(data) + 1)
bar_height = 40
bar_width = 60
offset = 30
spacing = 10
if color_array is None:
color_array = ["red" for _ in data]
for i, height in enumerate(data):
x0 = i * (bar_width + spacing)+offset
y0 = canvas_height//2 - bar_height//2
x1 = x0 + bar_width
y1 = y0 + bar_height
color = color_array[i]
canvas.create_rectangle(x0, y0, x1, y1, fill=color)
canvas.create_text((x0 + x1) // 2, (y0 + y1) // 2, text=str(height), fill="white")
canvas.config(scrollregion=canvas.bbox("all"))
self.root.update_idletasks()
def draw_stack(self, data, canvas):
canvas.delete("all")
canvas_height = 180
canvas_width = 80
bar_width = 60
offset = 30
spacing = 10
for i, height in enumerate(data):
x0 = offset
y0 = canvas_height - (i + 1) * (bar_width + spacing)
x1 = offset + bar_width
y1 = canvas_height - i * (bar_width + spacing)
canvas.create_rectangle(x0, y0, x1, y1, fill="blue")
canvas.create_text((x0 + x1) // 2, (y0 + y1) // 2, text=str(height), fill="white")
canvas.config(scrollregion=canvas.bbox("all"))
self.root.update_idletasks()
def draw_linked_list(self, data, canvas):
canvas.delete("all")
canvas_height = 180
canvas_width = max(800, len(data) * 100)
bar_width = canvas_width / (len(data) + 1)
node_width=60
node_height = 40
offset = 30
spacing = 40
for i, value in enumerate(data):
x0 = i * (node_width + spacing) + offset
y0 = canvas_height // 2 - node_height // 2
x1 = x0 + node_width
y1 = y0 + node_height
canvas.create_rectangle(x0, y0, x1, y1, fill="green")
canvas.create_text((x0 + x1) // 2, (y0 + y1) // 2, text=str(value), fill="white")
if i < len(data) - 1:
x2 = x1 + spacing // 2
y2 = canvas_height // 2
x3 = x1 + spacing
canvas.create_line(x1, y2, x2, y2, arrow=tk.LAST, fill="black")
canvas.config(scrollregion=canvas.bbox("all"))
self.root.update_idletasks()
def draw_set(self, data, canvas):
canvas.delete("all")
canvas_height = 180
canvas_width = max(800, len(data) * 100)
bar_width = canvas_width / (len(data) + 1)
bar_height = 40
bar_width = 60
offset = 30
spacing = 10
for i, value in enumerate(data):
x0 = i * (bar_width + spacing)+offset
y0 = canvas_height//2 - bar_height//2
x1 = x0 + bar_width
y1 = y0 + bar_height
canvas.create_rectangle(x0, y0, x1, y1, fill="purple")
canvas.create_text((x0 + x1) // 2, (y0 + y1) // 2, text=str(value), fill="white")
canvas.config(scrollregion=canvas.bbox("all"))
self.root.update_idletasks()
def draw_dictionary(self, data, canvas):
canvas.delete("all")
canvas_height = 180
canvas_width = max(800, len(data) * 100)
bar_width = canvas_width / (len(data) + 1)
bar_height = 40
bar_width = 60
offset = 30
spacing = 10
for i, (key, value) in enumerate(data.items()):
x0 = i * (bar_width + spacing)+offset
y0 = canvas_height//2 - bar_height//2
x1 = x0 + bar_width
y1 = y0 + bar_height
canvas.create_rectangle(x0, y0, x1, y1, fill="orange")
canvas.create_text((x0 + x1) // 2, (y0 + y1) // 2 - 10, text=str(key), fill="white")
canvas.create_text((x0 + x1) // 2, (y0 + y1) // 2 + 10, text=str(value), fill="white")
canvas.config(scrollregion=canvas.bbox("all"))
self.root.update_idletasks()
def sort_and_visualize(self):
sorting_algo = self.sorting_algos.get()
values = self.data_entry.get()
if not sorting_algo or not values:
messagebox.showerror("Input Error", "Please select a sorting algorithm and enter values")
return
try:
self.data = list(map(int, values.split(',')))
except ValueError:
messagebox.showerror("Input Error", "Please enter valid integer values.")
return
if sorting_algo == "Bubble Sort":
self.bubble_sort(self.data)
elif sorting_algo == "Insertion Sort":
self.insertion_sort(self.data)
elif sorting_algo == "Quick Sort":
self.quick_sort(self.data, 0, len(self.data) - 1)
def bubble_sort(self, data):
self.explanation_text.delete("1.0", tk.END)
self.explanation_text.insert(tk.END, "Bubble Sort Explanation:\n\n")
n = len(data)
for i in range(n):
for j in range(0, n - i - 1):
if data[j] > data[j + 1]:
data[j], data[j + 1] = data[j + 1], data[j]
self.draw_array(data, self.canvas_sorting, ["green" if x == data[j] else "red" if x == data[j+1] else "gray" for x in data])
self.explanation_text.insert(tk.END, f"Swapped {data[j+1]} and {data[j]}\n")
self.root.update()
time.sleep(1)
self.draw_array(data, self.canvas_sorting, ["green" for _ in data])
def insertion_sort(self, data):
self.explanation_text.delete("1.0", tk.END)
self.explanation_text.insert(tk.END, "Insertion Sort Explanation:\n\n")
for i in range(1, len(data)):
key = data[i]
j = i - 1
while j >= 0 and key < data[j]:
data[j + 1] = data[j]
j -= 1
self.draw_array(data, self.canvas_sorting, ["green" if x == key else "red" if x == data[j+1] else "gray" for x in data])
self.explanation_text.insert(tk.END, f"Moved {data[j+1]} to position {j+2}\n")
self.root.update()
time.sleep(1)
data[j + 1] = key
self.draw_array(data, self.canvas_sorting, ["green" if x == key else "gray" for x in data])
self.explanation_text.insert(tk.END, f"Inserted {key} at position {j+1}\n")
self.draw_array(data, self.canvas_sorting, ["green" for _ in data])
def quick_sort(self, data, low, high):
if low < high:
pi = self.partition(data, low, high)
self.quick_sort(data, low, pi - 1)
self.quick_sort(data, pi + 1, high)
def partition(self, data, low, high):
self.explanation_text.delete("1.0", tk.END)
self.explanation_text.insert(tk.END, "Quick Sort Explanation:\n\n")
i = low - 1
pivot = data[high]
for j in range(low, high):
if data[j] < pivot:
i += 1
data[i], data[j] = data[j], data[i]
self.draw_array(data, self.canvas_sorting, ["green" if x == pivot else "red" if x == data[i] else "gray" for x in data])
self.explanation_text.insert(tk.END, f"Swapped {data[i]} with {data[j]}\n")
self.root.update()
time.sleep(1)
data[i + 1], data[high] = data[high], data[i + 1]
self.draw_array(data, self.canvas_sorting, ["green" if x == pivot else "red" if x == data[i+1] else "gray" for x in data])
self.explanation_text.insert(tk.END, f"Moved pivot {pivot} to correct position\n")
return i + 1
if __name__ == "__main__":
root = tk.Tk()
app = VisualizerApp(root)
root.mainloop()
我期待主窗口有一个滚动条,可以滚动所有画布,还有第三个画布的滚动条。
在运行之前将所有三个根包移至末尾。
self.scroll_y.pack(side=tk.RIGHT, fill=tk.Y)
self.scroll_x.pack(side=tk.BOTTOM, fill=tk.X)
self.canvas.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
def on_frame_configure(self, event):
您无法垂直和水平滚动。除非你在 Canvas 中添加小部件。
更改垂直和水平方向:
tk.Scrollbar(self.data_frame,
至:
tk.Scrollbar(self.canvas_data_structure,
还有这个:
tk.Scrollbar(self.sorting_canvas_frame,
至:
tk.Scrollbar(self.canvas_sorting
仅在调整大小时截图:
代表canvas_sorting的第三个画布的滚动条应该配置为在所有画布之间正确滚动。更具体地说,我们需要执行以下操作:
为名为canvas_sorting的第三个画布配置滚动条。 确保所有滚动条都正确绑定到各自的画布。
将在下面的代码中进行更改以实现这些。
将 tkinter 导入为 tk 从 tkinter 导入 ttk、消息框 将 matplotlib.pyplot 导入为 plt 导入时间
VisualizerApp 类: def init(自身,根): self.root = 根 self.root.title("数据结构与排序算法") self.root.geometry("1200x800")
# Canvas for the Main Window
self.canvas = tk.Canvas(root)
self.canvas.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
# Scrollbars for the main window
self.scroll_x = tk.Scrollbar(root, orient=tk.HORIZONTAL, command=self.canvas.xview)
self.scroll_x.pack(side=tk.BOTTOM, fill=tk.X)
self.scroll_y = tk.Scrollbar(root, orient=tk.VERTICAL, command=self.canvas.yview)
self.scroll_y.pack(side=tk.RIGHT, fill=tk.Y)
# Frame for the widgets
self.frame = tk.Frame(self.canvas)
self.canvas.create_window((0, 0), window=self.frame, anchor='nw')
# Configure Canvas scrolling
self.frame.bind("<Configure>", self.on_frame_configure)
self.canvas.config(xscrollcommand=self.scroll_x.set, yscrollcommand=self.scroll_y.set)
# Setup UI
self.setup_ui()
def setup_ui(self):
# Frame for data structure selection and visualization
self.data_frame = tk.Frame(self.frame)
self.data_frame.pack(padx=10, pady=10, fill=tk.BOTH, expand=True)
# Dropdown menus for data structures
tk.Label(self.data_frame, text="Select Data Structure:", fg="black").pack(padx=10, pady=5, anchor=tk.W)
options = ["Array", "Stack", "Linked List", "Set", "Tuple", "Dictionary"]
self.data_structure = tk.StringVar(value=options[0])
data_structure_menu = tk.OptionMenu(self.data_frame, self.data_structure, *options)
data_structure_menu.pack(padx=10, pady=5, anchor=tk.W)
# Entry for the values
tk.Label(self.data_frame, text="Enter Values (Comma Separated):", fg="black").pack(padx=10, pady=5, anchor=tk.W)
self.data_entry = tk.Entry(self.data_frame)
self.data_entry.pack(padx=10, pady=5, anchor=tk.W)
# Canvas for visualizing data structures
self.canvas_data_structure = tk.Canvas(self.data_frame, bg="white", width=1000, height=300)
self.canvas_data_structure.pack(padx=10, pady=5, fill=tk.BOTH, expand=True)
# Scrollbars for data structure canvas
self.scroll_x_data = tk.Scrollbar(self.data_frame, orient=tk.HORIZONTAL, command=self.canvas_data_structure.xview)
self.scroll_x_data.pack(side=tk.BOTTOM, fill=tk.X)
self.canvas_data_structure.config(xscrollcommand=self.scroll_x_data.set)
self.scroll_y_data = tk.Scrollbar(self.data_frame, orient=tk.VERTICAL, command=self.canvas_data_structure.yview)
self.scroll_y_data.pack(side=tk.RIGHT, fill=tk.Y)
self.canvas_data_structure.config(yscrollcommand=self.scroll_y_data.set)
# Button for visualizing data structure
self.visualize_button = tk.Button(self.data_frame, text="Visualize Data Structure", command=self.visualize_data_structure)
self.visualize_button.pack(padx=10, pady=5)
# Frame for sorting algorithm selection and visualization
self.sort_frame = tk.Frame(self.frame)
self.sort_frame.pack(padx=10, pady=10, fill=tk.BOTH, expand=True)
# Dropdown menu for sorting algorithms
tk.Label(self.sort_frame, text="Select Sorting Algorithm:", fg="black").pack(padx=10, pady=5, anchor=tk.W)
options2 = ["Bubble Sort", "Insertion Sort", "Quick Sort"]
self.sorting_algos = tk.StringVar(value=options2[0])
sorting_algorithm_menu = tk.OptionMenu(self.sort_frame, self.sorting_algos, *options2)
sorting_algorithm_menu.pack(padx=10, pady=5, anchor=tk.W)
# Button for sort and visualize
self.sort_button = tk.Button(self.sort_frame, text="Sort and Visualize", command=self.sort_and_visualize)
self.sort_button.pack(padx=10, pady=5)
# Frame and canvas for sorting visualization
self.sorting_canvas_frame = tk.Frame(self.sort_frame)
self.sorting_canvas_frame.pack(padx=10, pady=5, fill=tk.BOTH, expand=True)
self.canvas_sorting = tk.Canvas(self.sorting_canvas_frame, bg="white", width=1000, height=300)
self.canvas_sorting.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
# Scrollbars for sorting canvas
self.scroll_x_sort = tk.Scrollbar(self.sorting_canvas_frame, orient=tk.HORIZONTAL, command=self.canvas_sorting.xview)
self.scroll_x_sort.pack(side=tk.BOTTOM, fill=tk.X)
self.canvas_sorting.config(xscrollcommand=self.scroll_x_sort.set)
self.scroll_y_sort = tk.Scrollbar(self.sorting_canvas_frame, orient=tk.VERTICAL, command=self.canvas_sorting.yview)
self.scroll_y_sort.pack(side=tk.RIGHT, fill=tk.Y)
self.canvas_sorting.config(yscrollcommand=self.scroll_y_sort.set)
# Text area for the explanation
self.explanation_frame = tk.Frame(self.frame)
self.explanation_frame.pack(padx=10, pady=10, fill=tk.BOTH, expand=True)
self.explanation_text = tk.Text(self.explanation_frame, height=10, width=100)
self.explanation_text.pack(padx=10, pady=5, fill=tk.BOTH, expand=True)
def on_frame_configure(self, event):
self.canvas.config(scrollregion=self.canvas.bbox("all"))
self.canvas_data_structure.config(scrollregion=self.canvas_data_structure.bbox("all"))
self.canvas_sorting.config(scrollregion=self.canvas_sorting.bbox("all"))
def visualize_data_structure(self):
data_type = self.data_structure.get()
values = self.data_entry.get()
if not data_type or not values:
messagebox.showerror("Input Error", "Please select a data structure and enter values")
return
try:
self.data = list(map(int, values.split(',')))
except ValueError:
messagebox.showerror("Input Error", "Please enter valid integer values.")
return
if data_type == "Array" or data_type == "Tuple":
self.draw_array(self.data, self.canvas_data_structure)
elif data_type == "Stack":
self.draw_stack(self.data, self.canvas_data_structure)
elif data_type == "Linked List":
self.draw_linked_list(self.data, self.canvas_data_structure)
elif data_type == "Set":
self.draw_set(set(self.data), self.canvas_data_structure)
elif data_type == "Dictionary":
self.draw_dictionary({i: val for i, val in enumerate(self.data)}, self.canvas_data_structure)
def draw_array(self, data, canvas, color_array=None):
canvas.delete("all")
canvas_height = 180
canvas_width = max(800, len(data) * 100)
bar_width = canvas_width / (len(data) + 1)
bar_height = 40
bar_width = 60
offset = 30
spacing = 10
if color_array is None:
color_array = ["red" for _ in data]
for i, height in enumerate(data):
x0 = i * (bar_width + spacing)+offset
y0 = canvas_height//2 - bar_height//2
x1 = x0 + bar_width
y1 = y0 + bar_height
color = color_array[i]
canvas.create_rectangle(x0, y0, x1, y1, fill=color)
canvas.create_text((x0 + x1) // 2, (y0 + y1) // 2, text=str(height), fill="white")
canvas.config(scrollregion=canvas.bbox("all"))
self.root.update_idletasks()
def draw_stack(self, data, canvas):
canvas.delete("all")
canvas_height = 180
canvas_width = 80
bar_width = 60
offset = 30
spacing = 10
for i, height in enumerate(data):
x0 = offset
y0 = canvas_height - (i + 1) * (bar_width + spacing)
x1 = offset + bar_width
y1 = canvas_height - i * (bar_width + spacing)
canvas.create_rectangle(x0, y0, x1, y1, fill="blue")
canvas.create_text((x0 + x1) // 2, (y0 + y1) // 2, text=str(height), fill="white")
canvas.config(scrollregion=canvas.bbox("all"))
self.root.update_idletasks()
def draw_linked_list(self, data, canvas):
canvas.delete("all")
canvas_height = 180
canvas_width = max(800, len(data) * 100)
bar_width = canvas_width / (len(data) + 1)
node_width=60