【问题标题】:Tkinter scrollable frame inside function函数内部的 Tkinter 可滚动框架
【发布时间】:2021-09-14 16:34:40
【问题描述】:

我正在尝试构建一个打开文件浏览器并在可滚动框架中列出所选文件的函数。我尝试使用我在网上找到的可滚动框架类,当我将它应用于一个非常简单的案例时,它可以工作,但在我的文件浏览功能中应用时不起作用。可滚动框架类的写法如下:

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()

如果文件列表继续超出窗口范围并且滚动条不起作用且很小,则会产生以下结果。

image of tkinter window with scrollable frame

非常感谢任何帮助。

【问题讨论】:

  • 使用canvas.grid(row=0, column=0, sticky="news")scrollbar.grid(row=0, column=1, sticky="ns")。此外,您还需要将所有要滚动的小部件放在 self.scrollable_frame 中,所以不要使用 Label(files, ...) 使用 Label(files.scrollable_frame, ...)
  • 为什么不使用列表框?那会容易得多
  • @TheLizzard,谢谢,这似乎已经解决了问题!
  • @BryanOakley tkinnter 中的列表框和框架有什么区别?
  • @Madmem 框架是其他小部件的空容器。列表框是专门用于显示字符串列表的可滚动小部件。

标签: python tkinter scrollbar


【解决方案1】:

您的课程在 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()

注意标签是如何在画布之外的。这是因为您实际上是将它放在包含画布的框架中,而不是画布内部的框架中。要修复它,只需使用tk.Label(frame.scrollable_frame, text="Test")。这将迫使标签进入画布内部的框架内,而不是包裹所有东西的框架内。

如果您想要改进课程,请查看我不久前写的 this 答案。

【讨论】:

  • 感谢您,这对您有很大帮助!我有一个后续问题,如何更改画布/可滚动区域的大小?我有另一个非常相似的代码,每个文件的右侧都有条目,但是当我尝试应用它时,框架会切断部分条目。
  • @Madmem 为此,您需要将画布保存在 self.canvas 中,以便您可以调用 self.canvas.config(width=&lt;new width&gt;, height=&lt;new height&gt;)。所有tkinter 小部件都有.config 方法,因此您可以使用它来更改它们的任何参数。您可能还需要致电self.canvas.configure(scrollregion=self.canvas.bbox("all"))
猜你喜欢
  • 2015-07-13
  • 1970-01-01
  • 2015-04-18
  • 1970-01-01
  • 2013-04-17
  • 2021-09-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多