Python Tkinter可滚动画布在顶部创建额外的滚动区域

Python Tkinter可滚动画布在顶部创建额外的滚动区域,python,canvas,tkinter,scrollbar,frame,Python,Canvas,Tkinter,Scrollbar,Frame,我对python3上的Tkinter非常陌生,并且尝试在画布上制作一个可滚动的框架。 我可以为默认窗口大小创建它,没有问题。但是当窗口最大化时,,画布突然在顶部添加了额外的可滚动区域,我一直在寻找方法删除它/保持可滚动框架在顶部 import tkinter as tk class MainWindow(tk.Tk): def __init__(self, *args, **kwargs): super().__init__() self.geome

我对python3上的Tkinter非常陌生,并且尝试在画布上制作一个可滚动的框架。 我可以为默认窗口大小创建它,没有问题。但是当窗口最大化时,,画布突然在顶部添加了额外的可滚动区域,我一直在寻找方法删除它/保持可滚动框架在顶部

import tkinter as tk


class MainWindow(tk.Tk):

    def __init__(self, *args, **kwargs):
        super().__init__()
        self.geometry("1500x800")
        self.configure(background="#303030")


class Table(tk.Frame):

    def __init__(self, master, rows=2, columns=2):

        tk.Frame.__init__(self, master, background="#36363d")

        # Set table as list of rows
        self.table = []
        for row in range(rows):

            # Create list to store cell info in a rows
            current_row = []
            for column in range(columns):

                label = tk.Label(self, text="", borderwidth=0, width=columns, bg="#474756", )
                label.grid(row=row, column=column, sticky="nsew", padx=1, pady=1, )

                # Append cell (column) into rows
                current_row.append(label)

            # Append rows into whole table
            self.table.append(current_row)

        for column in range(columns):
            self.grid_columnconfigure(column, weight=1)


class ScrollablePage(tk.Frame):

    def __init__(self, master, *args, **kw):
        super().__init__(master)

        self.canvas = tk.Canvas(self, borderwidth=0, highlightthickness=0, bg="red")    # THIS TO EMPHASIZE THE CANVAS,

        self.frame = tk.Frame(self.canvas, *args, **kw)
        self.vsb = tk.Scrollbar(self, orient="vertical", command=self.canvas.yview)
        self.canvas.configure(yscrollcommand=self.vsb.set)

        self.vsb.pack(side="right", fill="y")
        self.canvas.pack(side="left", fill="both", expand=True)
        self.canvas_frame = self.canvas.create_window((0, 0), window=self.frame, anchor="nw", tags="self.frame")

        # Dynamic frame setup
        self.frame.bind("<Configure>", self.frame_conf)
        self.canvas.bind("<Configure>", self.frame_width)

        # Bind canvas to mousewheel
        self.canvas.bind("<Enter>", self.bound_to_mousewheel)
        self.canvas.bind("<Leave>", self.unbound_to_mousewheel)

    def frame_conf(self, event):
        """
        Reset the scroll region to encompass the inner frame
        """

        self.canvas.configure(scrollregion=self.canvas.bbox("all"))

    def frame_width(self, event):
        """
        Function to adjust canvas's frame upon expand (can't use pack)
        """

        self.canvas.itemconfig(self.canvas_frame, width=event.width)

    def mouse_wheel(self, event):
        """
        Capture mouse wheel changes to scroll page
        """
        self.canvas.yview_scroll(-1 * int(event.delta / 60), "units")

    def bound_to_mousewheel(self, event):
        self.canvas.bind_all("<MouseWheel>", self.mouse_wheel)

    def unbound_to_mousewheel(self, event):
        self.canvas.unbind_all("<MouseWheel>")


class PageTwo(ScrollablePage):

    def __init__(self, master):

        # Create page
        super().__init__(master, bg="#36363d")

        # EXAMPLE CONTENT
        controller = tk.Frame(self.frame, bg="#474756", width=0.9 * 1500, height=200, bd=0,)
        controller.pack(side="top", fill="x", padx=20, pady=10)

        self.table = Table(self.frame, rows=20, columns=10)
        self.table.pack(side="top", fill="both", padx=20, expand=1)


class MainContent(tk.Frame):

    # Setup main content's stacked-frame
    frames = {}

    # main_content_classes = [PageOne, PageTwo, PageThree, PageFour, PageFive, PageSix, PageDefault]  # << ORIGINAL ONE
    main_content_classes = [PageTwo]

    def __init__(self, master):

        # Create main content's frame
        super().__init__(master)

        # Place main content's frame in main window
        self.place(x=150, y=130, relwidth=0.9, relheight=0.83)

        # Create grid inside main content frame
        self.grid_rowconfigure(0, weight=1)
        self.grid_columnconfigure(0, weight=1)

        # Stacking pages in main content
        for FrameClass in MainContent.main_content_classes:
            page_name = FrameClass.__name__
            frame = FrameClass(self)
            frame.grid(row=0, column=0, sticky="nsew")
            MainContent.frames[page_name] = frame


class Datalab:

    def __init__(self, *args, **kwargs):

        main_window = MainWindow()
        MainContent(main_window)
        main_window.mainloop()

if __name__ == "__main__":
    app = Datalab()
将tkinter作为tk导入
类主窗口(tk.tk):
定义初始化(self,*args,**kwargs):
super()。\uuuu init\uuuuu()
自几何(“1500x800”)
自我配置(后台=“#303030”)
类表(tk.Frame):
定义初始化(self,master,行=2,列=2):
tk.Frame.uuu init_uuuu(self,master,background=“#36363d”)
#将表设置为行列表
self.table=[]
对于范围内的行(行):
#创建列表以在行中存储单元格信息
当前_行=[]
对于范围内的列(列):
label=tk.label(self,text=,borderwidth=0,width=columns,bg=“#474756”,)
label.grid(行=行,列=列,sticky=“nsew”,padx=1,pady=1,)
#将单元格(列)追加到行中
当前_行。追加(标签)
#将行追加到整个表中
self.table.append(当前_行)
对于范围内的列(列):
self.grid\u columnconfigure(列,权重=1)
类可滚动页面(tk.Frame):
定义初始值(自、主、*args、**kw):
超级()。\uuuu初始化\uuuuu(主)
self.canvas=tk.canvas(self,borderwidth=0,highlightthickness=0,bg=“red”)#这是为了强调画布,
self.frame=tk.frame(self.canvas,*args,**kw)
self.vsb=tk.Scrollbar(self,orient=“vertical”,command=self.canvas.yview)
self.canvas.configure(yscrollcommand=self.vsb.set)
自包装(side=“right”,fill=“y”)
self.canvas.pack(side=“left”,fill=“both”,expand=True)
self.canvas\u frame=self.canvas.create\u window((0,0),window=self.frame,anchor=“nw”,tags=“self.frame”)
#动态帧设置
self.frame.bind(“,self.frame_conf)
self.canvas.bind(“,self.frame\u宽度)
#将画布绑定到鼠标滚轮
self.canvas.bind(“,self.bind_到_鼠标滚轮)
self.canvas.bind(“,self.unbound\u to\u mouseweel)
def帧配置(自身,事件):
"""
重置滚动区域以包围内部框架
"""
self.canvas.configure(scrollregion=self.canvas.bbox(“全部”))
def帧_宽度(自身、事件):
"""
展开时调整画布框架的功能(不能使用pack)
"""
self.canvas.itemconfig(self.canvas\u frame,width=event.width)
def鼠标滚轮(自身、事件):
"""
捕获鼠标滚轮更改以滚动页面
"""
self.canvas.yview_滚动(-1*int(event.delta/60),“单位”)
def绑定到鼠标滚轮(自身、事件):
self.canvas.bind\u all(“,self.mouse\u wheel)
def未绑定鼠标滚轮(自身、事件):
self.canvas.unbind_all(“”)
第二类页面(可滚动页面):
定义初始(自我,主):
#创建页面
超级()
#示例内容
控制器=tk.Frame(self.Frame,bg=“#47474756”,宽度=0.9*1500,高度=200,bd=0,)
控制器包(side=“top”,fill=“x”,padx=20,pady=10)
self.table=table(self.frame,行=20,列=10)
self.table.pack(side=“top”,fill=“both”,padx=20,expand=1)
类主内容(tk.Frame):
#设置主要内容的堆叠框架
帧={}

#main_content_classes=[PageOne,PageTwo,PageThree,PageFour,PageFive,PageSix,PageDefault]。我遇到了同样的问题,发现
vsb.get()
方法在窗口中显示所有内容(最大化,或者滚动区域中的项目不多)时返回tuple
(0.0,1.0)
。我不知道这个解决方案有多脏,但这对我有用

鼠标滚轮应仅在滚动条可滚动时生效:

def mouse_wheel(self, event):
    """
    Capture mouse wheel changes to scroll page
    """
    if self.vsb.get() != (0.0, 1.0):
        self.canvas.yview_scroll(-1 * int(event.delta / 60), "units")

创建最小的工作示例,以便我们可以将其作为see problem.edit question运行,并使用按钮
{}
正确格式化代码-当前您有错误的缩进。如果框架比画布小,则必须在框架下看到红色画布-或使用
canvas.itemconfig(self.canvas\u frame,height=event.height)
自动更改框架高度(类似于
宽度
)。请验证上述代码片段是否正确。@如果我已更新代码,请再次检查,谢谢。。谢谢你是怎么发现。。。它起作用了!!我使用了额外的填充,但现在我不再需要了:>我正在寻找一个很好的滚动框架实现,里面有很多小部件,你的工作非常好。所以我很高兴我们都互相帮助:)