简体   繁体   English

函数内的 Tkinter 可滚动框架

[英]Tkinter scrollable frame inside function

I'm trying to build a function which opens a file browser and lists the selected files in a scrollable frame.我正在尝试构建一个函数,该函数打开文件浏览器并在可滚动框架中列出所选文件。 I tried using a scrollable frame class I found on the web which works when I apply it to a very simple case, but does not work when applied inside my file browsing function.我尝试使用我在网络上找到的可滚动框架类,当我将它应用于一个非常简单的案例时该类有效,但在我的文件浏览功能中应用时不起作用。 The scrollable frame class is written as follows:可滚动框架类的写法如下:

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)

and then is applied by:然后通过以下方式应用:

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

which produces the following result where the file list continues beyond the span of the window and the scrollbar is nonfunctional and small.这会产生以下结果,其中文件列表继续超出窗口的范围并且滚动条不起作用且很小。

image of tkinter window with scrollable frame带有可滚动框架的 tkinter 窗口的图像

Any help is greatly appreciated.任何帮助是极大的赞赏。

Your class is flawed in 1 big way.您的课程在一大方面存在缺陷。 When you use:当您使用:

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

Notice how the label is outside of the canvas.注意标签如何在画布之外。 This is because you are actually putting it in the frame that contains the canvas not the frame that is inside the canvas.这是因为您实际上是将它放在包含画布的框架中,而不是放在画布内部的框架中。 To fix it just use tk.Label(frame.scrollable_frame, text="Test") .要修复它,只需使用tk.Label(frame.scrollable_frame, text="Test") That will force the label to go inside of the frame that is inside the canvas not the frame that wraps everything.这将强制标签进入画布内的框架内,而不是包装所有内容的框架内。

If you want an improved class, look at this answer that I wrote a while back.如果您想要改进的课程,请查看我不久前写的这个答案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM