Tkinter 可滚动框架内部功能
Tkinter scrollable frame inside function
我正在尝试构建一个打开文件浏览器并在可滚动框架中列出所选文件的功能。我尝试使用我在网上找到的可滚动框架 class,当我将它应用到一个非常简单的案例时它可以工作,但是当我在我的文件浏览功能中应用时它不起作用。可滚动框class写法如下:
class ScrollableFrame(ttk.Frame):
def __init__(self, container, *args, **kwargs):
super().__init__(container, *args, **kwargs)
canvas = tk.Canvas(self)
scrollbar = ttk.Scrollbar(self, orient="vertical", command=canvas.yview)
self.scrollable_frame = ttk.Frame(canvas)
self.scrollable_frame.bind(
"<Configure>",
lambda e: canvas.configure(
scrollregion=canvas.bbox("all")))
canvas.create_window((0, 0), window=self.scrollable_frame, anchor="nw")
canvas.configure(yscrollcommand=scrollbar.set)
canvas.grid(row=0, column=0)
scrollbar.grid(row = 0, column=1)
然后被应用:
import os
from tkinter import filedialog,Label,Tk,Entry,Frame,ttk
import tkinter as tk
root = Tk()
browse_frame = Frame(root)
browse_frame.grid(row=0, column=0, columnspan=2)
all_files = []
def browse_files():
#function which opens a file browser and adds selected files to all_files list.
#opens file browser
filename_list = list(filedialog.askopenfilenames(initialdir = '/',
title = "Select Files",
filetypes = (("text files","*.txt"),
("csv files","*.csv"),
("all files","*.*"))))
#adds selected files to all_files list
for i in filename_list:
all_files.append(i)
if len(all_files) >=1:
#build scrollable frame for file names
files = ScrollableFrame(root)
files.grid(column=0, row=3, padx=10, pady=10)
file_label = Label(files, text="Selected Files:", font=("arial", 13))
file_label.grid(column=0, row=0, padx=80, pady=10)
u = 0
while u < len(all_files):
#adds each file name to scrollable frame
file_name = Label(files, text=str(os.path.basename(all_files[u])))
file_name.grid(column=0, row=u+1, padx=5, pady=5)
u+=1
return
browse = ttk.Button(browse_frame, text="browse files", command=browse_files)
browse.grid(column=1, row=0, rowspan=2, padx=50, pady=10)
root.mainloop()
这会产生以下结果,其中文件列表继续超出 window 的范围并且滚动条不起作用且很小。
image of tkinter window with scrollable frame
非常感谢任何帮助。
您的 class 存在 1 个重大缺陷。当您使用:
import tkinter as tk
class ScrollableFrame(tk.Frame):
def __init__(self, container, *args, **kwargs):
super().__init__(container, *args, **kwargs)
# Note the `bg="red"`. It's just to show where the canvas is.
# Remove it later
canvas = tk.Canvas(self, bg="red")
scrollbar = tk.Scrollbar(self, orient="vertical", command=canvas.yview)
self.scrollable_frame = tk.Frame(canvas)
self.scrollable_frame.bind(
"<Configure>",
lambda e: canvas.configure(
scrollregion=canvas.bbox("all")))
canvas.create_window((0, 0), window=self.scrollable_frame, anchor="nw")
canvas.configure(yscrollcommand=scrollbar.set)
canvas.grid(row=0, column=0, sticky="news")
scrollbar.grid(row=0, column=1, sticky="ns")
root = tk.Tk()
frame = ScrollableFrame(root)
frame.pack()
label = tk.Label(frame, text="Test")
label.grid()
root.mainloop()
注意标签是如何在 canvas 之外的。这是因为您实际上是将它放在包含 canvas 的框架中,而不是 canvas 内的框架中。要修复它,只需使用 tk.Label(frame.scrollable_frame, text="Test")
。这将迫使标签进入 canvas 内部的框架,而不是包裹所有内容的框架。
如果您想要改进的 class,请查看我不久前写的 this 答案。
我正在尝试构建一个打开文件浏览器并在可滚动框架中列出所选文件的功能。我尝试使用我在网上找到的可滚动框架 class,当我将它应用到一个非常简单的案例时它可以工作,但是当我在我的文件浏览功能中应用时它不起作用。可滚动框class写法如下:
class ScrollableFrame(ttk.Frame):
def __init__(self, container, *args, **kwargs):
super().__init__(container, *args, **kwargs)
canvas = tk.Canvas(self)
scrollbar = ttk.Scrollbar(self, orient="vertical", command=canvas.yview)
self.scrollable_frame = ttk.Frame(canvas)
self.scrollable_frame.bind(
"<Configure>",
lambda e: canvas.configure(
scrollregion=canvas.bbox("all")))
canvas.create_window((0, 0), window=self.scrollable_frame, anchor="nw")
canvas.configure(yscrollcommand=scrollbar.set)
canvas.grid(row=0, column=0)
scrollbar.grid(row = 0, column=1)
然后被应用:
import os
from tkinter import filedialog,Label,Tk,Entry,Frame,ttk
import tkinter as tk
root = Tk()
browse_frame = Frame(root)
browse_frame.grid(row=0, column=0, columnspan=2)
all_files = []
def browse_files():
#function which opens a file browser and adds selected files to all_files list.
#opens file browser
filename_list = list(filedialog.askopenfilenames(initialdir = '/',
title = "Select Files",
filetypes = (("text files","*.txt"),
("csv files","*.csv"),
("all files","*.*"))))
#adds selected files to all_files list
for i in filename_list:
all_files.append(i)
if len(all_files) >=1:
#build scrollable frame for file names
files = ScrollableFrame(root)
files.grid(column=0, row=3, padx=10, pady=10)
file_label = Label(files, text="Selected Files:", font=("arial", 13))
file_label.grid(column=0, row=0, padx=80, pady=10)
u = 0
while u < len(all_files):
#adds each file name to scrollable frame
file_name = Label(files, text=str(os.path.basename(all_files[u])))
file_name.grid(column=0, row=u+1, padx=5, pady=5)
u+=1
return
browse = ttk.Button(browse_frame, text="browse files", command=browse_files)
browse.grid(column=1, row=0, rowspan=2, padx=50, pady=10)
root.mainloop()
这会产生以下结果,其中文件列表继续超出 window 的范围并且滚动条不起作用且很小。
image of tkinter window with scrollable frame
非常感谢任何帮助。
您的 class 存在 1 个重大缺陷。当您使用:
import tkinter as tk
class ScrollableFrame(tk.Frame):
def __init__(self, container, *args, **kwargs):
super().__init__(container, *args, **kwargs)
# Note the `bg="red"`. It's just to show where the canvas is.
# Remove it later
canvas = tk.Canvas(self, bg="red")
scrollbar = tk.Scrollbar(self, orient="vertical", command=canvas.yview)
self.scrollable_frame = tk.Frame(canvas)
self.scrollable_frame.bind(
"<Configure>",
lambda e: canvas.configure(
scrollregion=canvas.bbox("all")))
canvas.create_window((0, 0), window=self.scrollable_frame, anchor="nw")
canvas.configure(yscrollcommand=scrollbar.set)
canvas.grid(row=0, column=0, sticky="news")
scrollbar.grid(row=0, column=1, sticky="ns")
root = tk.Tk()
frame = ScrollableFrame(root)
frame.pack()
label = tk.Label(frame, text="Test")
label.grid()
root.mainloop()
注意标签是如何在 canvas 之外的。这是因为您实际上是将它放在包含 canvas 的框架中,而不是 canvas 内的框架中。要修复它,只需使用 tk.Label(frame.scrollable_frame, text="Test")
。这将迫使标签进入 canvas 内部的框架,而不是包裹所有内容的框架。
如果您想要改进的 class,请查看我不久前写的 this 答案。