画布内部的 tkinter 框架未扩展以填充区域

我有一个可滚动框架类,是从我发现的一些代码中借用的,但我无法调整它以满足我的需求。它是由 .pack() 管理的,但我需要使用 .grid(),所以我只是将一个框架 ( self.region) 打包到其中,这样我就可以在其中网格化我的小部件。但是,该框架内的小部件不会扩展以符合容器的边缘,我不确定为什么。那里有很多与我类似的问题,但似乎没有一个解决方案有帮助。我尝试使用.grid_columnconfigure.columnconfigure()、 ,但.bind("Configure")都无济于事。有没有人有任何建议让我的可滚动区域中的小部件向东和向西扩展以填充窗口?

import tkinter as tk

from tkinter import ttk


class ScrollableFrame(ttk.Frame):

    """taken from https://blog.tecladocode.com/tkinter-scrollable-frames/ and modified to

    allow for the use of grid inside self.region

    Class that allows for the creation of a frame that is scrollable"""

    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)

        canvas.create_window((0, 0), window=self.scrollable_frame, anchor="nw")

        canvas.configure(yscrollcommand=scrollbar.set)

        canvas.pack(side="left", fill="both", expand=True)

        canvas.rowconfigure(0, weight=1)

        canvas.columnconfigure(0, weight=1)

        scrollbar.pack(side="right", fill="y")

        self.scrollable_frame.bind(

            "<Configure>",

            lambda e: canvas.configure(

                scrollregion=canvas.bbox("all")

            )

        )

        self.scrollable_frame.rowconfigure(0, weight=1)

        self.scrollable_frame.columnconfigure(0, weight=1)

        self.region=ttk.Frame(self.scrollable_frame)

        self.region.pack(fill='both', expand=1)

        self.region.grid_rowconfigure(0, weight=1)

        self.region.grid_columnconfigure(0, weight=1)


https://img2.mukewang.com/64db3a410001a9e906530290.jpg


叮当猫咪
浏览 99回答 1
1回答

慕姐4208626

问题是滚动框架容器Frame没有Canvas水平填充。我不会费心修复一些复制/粘贴(例如滚动框架)并解释它,而是只给您我的滚动框架。它比您正在使用的要强大得多,而且您遇到的问题并不存在。我已经将其插入到下面的脚本版本中。在我的方法中找到了滚动框架问题的解决方案on_canvas_configure。它只是告诉容器框架在画布事件上与画布宽度相同<Configure>。import tkinter as tk, tkinter.ttk as ttkfrom typing import Iterable&nbsp; &nbsp;class ScrollFrame(tk.Frame):&nbsp; &nbsp; def __init__(self, master, scrollspeed=5, r=0, c=0, rspan=1, cspan=1, grid={}, **kwargs):&nbsp; &nbsp; &nbsp; &nbsp; tk.Frame.__init__(self, master, **{'width':400, 'height':300, **kwargs})&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; #__GRID&nbsp; &nbsp; &nbsp; &nbsp; self.grid(**{'row':r, 'column':c, 'rowspan':rspan, 'columnspan':cspan, 'sticky':'nswe', **grid})&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; #allow user to set width and/or height&nbsp; &nbsp; &nbsp; &nbsp; if {'width', 'height'} & {*kwargs}:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; self.grid_propagate(0)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; #give this widget weight on the master grid&nbsp; &nbsp; &nbsp; &nbsp; self.master.grid_rowconfigure(r, weight=1)&nbsp; &nbsp; &nbsp; &nbsp; self.master.grid_columnconfigure(c, weight=1)&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; #give self.frame weight on this grid&nbsp; &nbsp; &nbsp; &nbsp; self.grid_rowconfigure(0, weight=1)&nbsp; &nbsp; &nbsp; &nbsp; self.grid_columnconfigure(0, weight=1)&nbsp; &nbsp; &nbsp; &nbsp; #_WIDGETS&nbsp; &nbsp; &nbsp; &nbsp; self.canvas = tk.Canvas(self, bd=0, bg=self['bg'], highlightthickness=0, yscrollincrement=scrollspeed)&nbsp; &nbsp; &nbsp; &nbsp; self.canvas.grid(row=0, column=0, sticky='nswe')&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; self.frame&nbsp; &nbsp; = tk.Frame(self.canvas, **kwargs)&nbsp; &nbsp; &nbsp; &nbsp; self.frame_id = self.canvas.create_window((0, 0), window=self.frame, anchor="nw")&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; vsb = tk.Scrollbar(self, orient="vertical")&nbsp; &nbsp; &nbsp; &nbsp; vsb.grid(row=0, column=1, sticky='ns')&nbsp; &nbsp; &nbsp; &nbsp; vsb.configure(command=self.canvas.yview)&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; #attach scrollbar to canvas&nbsp; &nbsp; &nbsp; &nbsp; self.canvas.configure(yscrollcommand=vsb.set)&nbsp; &nbsp; &nbsp; &nbsp; #_BINDS&nbsp; &nbsp; &nbsp; &nbsp; #canvas resize&nbsp; &nbsp; &nbsp; &nbsp; self.canvas.bind("<Configure>", self.on_canvas_configure)&nbsp; &nbsp; &nbsp; &nbsp; #frame resize&nbsp; &nbsp; &nbsp; &nbsp; self.frame.bind("<Configure>", self.on_frame_configure)&nbsp; &nbsp; &nbsp; &nbsp; #scroll wheel&nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; self.canvas.bind_all('<MouseWheel>', self.on_mousewheel)&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp; &nbsp; #makes frame width match canvas width&nbsp; &nbsp; def on_canvas_configure(self, event):&nbsp; &nbsp; &nbsp; &nbsp; self.canvas.itemconfig(self.frame_id, width=event.width)&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp; &nbsp; #when frame dimensions change pass the area to the canvas scroll region&nbsp; &nbsp; def on_frame_configure(self, event):&nbsp; &nbsp; &nbsp; &nbsp; self.canvas.configure(scrollregion=self.canvas.bbox("all"))&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; #add scrollwheel feature&nbsp; &nbsp; def on_mousewheel(self, event):&nbsp; &nbsp; &nbsp; &nbsp; self.canvas.yview_scroll(int(-event.delta / abs(event.delta)), 'units')&nbsp; &nbsp; #configure self.frame row(s)&nbsp; &nbsp; def rowcfg(self, index, **options):&nbsp; &nbsp; &nbsp; &nbsp; index = index if isinstance(index, Iterable) else [index]&nbsp; &nbsp; &nbsp; &nbsp; for i in index:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; self.frame.grid_rowconfigure(i, **options)&nbsp; &nbsp; &nbsp; &nbsp; #so this can be used inline&nbsp; &nbsp; &nbsp; &nbsp; return self&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp; &nbsp; #configure self.frame column(s)&nbsp; &nbsp; def colcfg(self, index, **options):&nbsp; &nbsp; &nbsp; &nbsp; index = index if isinstance(index, Iterable) else [index]&nbsp; &nbsp; &nbsp; &nbsp; for i in index:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; self.frame.grid_columnconfigure(i, **options)&nbsp; &nbsp; &nbsp; &nbsp; #so this can be used inline&nbsp; &nbsp; &nbsp; &nbsp; return self&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;class AuxiliaryWindow(tk.Toplevel):&nbsp; &nbsp; def __init__(self, master, **kwargs):&nbsp; &nbsp; &nbsp; &nbsp; tk.Toplevel.__init__(self, master, **kwargs)&nbsp; &nbsp; &nbsp; &nbsp; self.geometry('600x300+600+200')&nbsp; &nbsp; &nbsp; &nbsp; self.attributes('-topmost', True)&nbsp; &nbsp; &nbsp; &nbsp; self.title('This Is Another Title') #:D&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; #if you reconsider things, you can accomplish more with less&nbsp; &nbsp; &nbsp; &nbsp; labels = ["this is a sort of long label",&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "this is another label",&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "Other information: blah blah blah blah"]&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; for i, text in enumerate(labels):&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ttk.Label(self, text=text).grid(row=0, column=i)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; self.grid_columnconfigure(i, weight=1)&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; #doing it this way the text will always fit the display as long as you give it enough height to work with&nbsp; &nbsp; &nbsp; &nbsp; instr = tk.Text(self, height=3, wrap='word', bg='gray94', font='Arial 8 bold', bd=0, relief='flat')&nbsp; &nbsp; &nbsp; &nbsp; instr.insert('1.0', ' '.join(['instructions']*20))&nbsp; &nbsp; &nbsp; &nbsp; instr.grid(row=1, columnspan=3, sticky='nswe')&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; #instantiate the scrollframe, configure the first 5 columns and return the frame. it's inline mania! :p&nbsp; &nbsp; &nbsp; &nbsp; self.scrollframe = ScrollFrame(self, 10, 2, 0, cspan=3).colcfg(range(5), weight=1).frame&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; self.fillScrollRegion()&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; #why store a reference to this? Do you intend to change/delete it later?&nbsp; &nbsp; &nbsp; &nbsp; ttk.Button(self, text="Do Something", command=self.do).grid(row=3, columnspan=3, sticky='ew')&nbsp; &nbsp; def fillScrollRegion(self):&nbsp; &nbsp; &nbsp; &nbsp; """fills scrollable region with label widgets"""&nbsp; &nbsp; &nbsp; &nbsp; r, c = 30, 5&nbsp; &nbsp; #math is our friend&nbsp; &nbsp; &nbsp; &nbsp; for i in range(r*c):&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ttk.Label(self.scrollframe, text=f"row_{i%r} col_{i//r}").grid(row=i%r, column=i//r, sticky='nsew')&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; def do(self):&nbsp; &nbsp; &nbsp; &nbsp; pass&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;class Root(tk.Tk):&nbsp; &nbsp; def __init__(self):&nbsp; &nbsp; &nbsp; &nbsp; tk.Tk.__init__(self)&nbsp; &nbsp; &nbsp; &nbsp; self.geometry('+550+150')&nbsp; &nbsp; &nbsp; &nbsp; self.title('This Is A Title Probably Or Something') #:D&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; aux = AuxiliaryWindow(self)&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; self.mainloop()Root() if __name__ == "__main__" else None
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Python