Python Tkinter中的可滚动框架

Python Tkinter中的可滚动框架,python,tkinter,widget,scrollbar,Python,Tkinter,Widget,Scrollbar,我正在尝试在Tkinter中创建一个框架,它将承载许多小部件,因此我需要使其可滚动。一般的解决方案是将此框架嵌入到画布中,并将该画布嵌入到另一个框架中 我设法做到了,但我有以下问题: 滚动条不会扩展到框架的整个高度 滚动条不会滚动帧 如果我使用canvas.create\u window((4,4),window=frame\u PSD\u channel\u registers,anchor='nw')滚动条会覆盖画布。在网格中使用列号没有任何区别 你知道怎么做吗 这是一段说明问题的代码 im

我正在尝试在
Tkinter
中创建一个
框架
,它将承载许多小部件,因此我需要使其可滚动。一般的解决方案是将此框架嵌入到画布中,并将该画布嵌入到另一个框架中

我设法做到了,但我有以下问题:

  • 滚动条不会扩展到框架的整个高度
  • 滚动条不会滚动帧
  • 如果我使用
    canvas.create\u window((4,4),window=frame\u PSD\u channel\u registers,anchor='nw')
    滚动条会覆盖画布。在
    网格
    中使用列号没有任何区别
  • 你知道怎么做吗

    这是一段说明问题的代码

    import tkinter as tk
    from tkinter import *
    from tkinter import ttk
    from tkinter import messagebox
    
    from PIL import ImageTk, Image
    
    import os
    
    # Method to make Label(Widget) invisible
    def hide_frame(frame):
        # This will remove the widget
        frame.grid_remove()
        
    # Method to make Label(widget) visible
    def show_frame(frame, c, r):
        # This will recover the widget
        frame.grid(column=c, row=r)
        
        
    def populate(frame):
        '''Put in some fake data'''
        for row in range(100):
            tk.Label(frame, text="%s" % row, width=3, borderwidth="1", 
                     relief="solid").grid(row=row, column=0)
            t="Blah blah blah blah blah blah blah blah %s" %row
            tk.Label(frame, text=t).grid(row=row, column=1)
        
    #____________________________________________________________________________________________   
    #This will be the main window
    window = tk.Tk()
    #window.geometry('1500x1200')
    window.attributes('-zoomed', True)
    window.title("daq")
    
    frame_main = Frame(window)
    frame_main.place(rely=0.10, relx=0.0, relwidth=1.0)
    
    #Create a tabcontrol
    tabControl = ttk.Notebook(frame_main)
    tabControl.grid(column=0, row=1)
    
    # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    #Digitizer tab
    tab_Digitizer    = ttk.Frame(tabControl)
    tabControl.add(tab_Digitizer, text='   Digitizer   ')
    digitizer_tab_dummy_label = Label(tab_Digitizer, text="")
    digitizer_tab_dummy_label.grid(column=0, row=0)
    
    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    #Channel settings
    
    lbl_channel_registers = Label(tab_Digitizer, text="Channel registers", font='bold')
    lbl_channel_registers.grid(column=0, row=3, sticky=W)
    
    frame_channel_registers = Frame(tab_Digitizer)
    frame_channel_registers.grid(column=0, row=4)
    
    btn_hide_channel_registers = Button(tab_Digitizer, text="Hide", fg="red", command=lambda: hide_frame(frame_channel_registers) )
    btn_hide_channel_registers.grid(column=1, row=3)
    
    
    btn_show_channel_registers = Button(tab_Digitizer, text="Show", fg="green", command=lambda: show_frame(frame_channel_registers, 0, 4))
    btn_show_channel_registers.grid(column=2, row=3)
    
    ##Channel settings - PSD
    
    def onFrameConfigure(event):
        '''Reset the scroll region to encompass the inner frame'''
        canvas.configure(scrollregion=canvas.bbox("all"))
    
    lbl_PSD_channel_registers = Label(frame_channel_registers, text="DPP-PSD registers")
    lbl_PSD_channel_registers.grid(column=0, row=3, padx=5, sticky=W)
    
    btn_hide_PSD_channel_registers = Button(frame_channel_registers, text="Hide", fg="red", command=lambda: hide_frame(canvas) )
    btn_hide_PSD_channel_registers.grid(column=1, row=3)
    
    
    btn_show_PSD_channel_registers = Button(frame_channel_registers, text="Show", fg="green", command=lambda: show_frame(canvas, 0, 4))
    btn_show_PSD_channel_registers.grid(column=2, row=3)
    
    canvas = tk.Canvas(frame_channel_registers, borderwidth=1, background="#FF0000")
    canvas.grid(column=0, row=4)
    
    frame_PSD_channel_registers = Frame(canvas, background="#0000FF")
    frame_PSD_channel_registers.grid(column=0, row=0, padx=25, sticky=W)
    
    myscrollbar=Scrollbar(canvas,orient="vertical",command=canvas.yview)
    myscrollbar.grid(column=2, row=0)
    canvas.configure(yscrollcommand=myscrollbar.set)
    
    #canvas.create_window((4,4),window=frame_PSD_channel_registers,anchor='nw')
    
    
    frame_PSD_channel_registers.bind("<Configure>", onFrameConfigure)
    
    populate(frame_PSD_channel_registers)
    
    
    #This keeps the window open - has to be at the end
    window.mainloop()
    
    将tkinter作为tk导入
    从tkinter进口*
    从tkinter导入ttk
    从tkinter导入消息框
    从PIL导入ImageTk,图像
    导入操作系统
    #方法使标签(小部件)不可见
    def隐藏_帧(帧):
    #这将删除小部件
    frame.grid_remove()
    #方法使标签(小部件)可见
    def显示U帧(帧,c,r):
    #这将恢复小部件
    框架网格(列=c,行=r)
    def填充(帧):
    ''输入一些假数据''
    对于范围(100)中的行:
    tk.Label(frame,text=“%s”%row,width=3,borderwidth=“1”,
    relief=“solid”).grid(行=行,列=0)
    t=“诸如此类诸如此类诸如此类%s”%row
    tk.Label(frame,text=t).grid(row=row,column=1)
    #____________________________________________________________________________________________   
    #这将是主窗口
    window=tk.tk()
    #窗口几何体('1500x1200')
    属性('-zomed',True)
    窗口名称(“daq”)
    主框架=框架(窗口)
    框架主位置(依赖=0.10,relx=0.0,relwidth=1.0)
    #创建选项卡控件
    tabControl=ttk.笔记本(主框架)
    tabControl.grid(列=0,行=1)
    # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    #数字化仪选项卡
    tab_数字化仪=ttk.Frame(tabControl)
    tabControl.add(tab_digitalizer,text='digitalizer')
    数字化仪\u选项卡\u虚拟\u标签=标签(选项卡\u数字化仪,文本=)
    数字化仪选项卡虚拟标签网格(列=0,行=0)
    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    #频道设置
    lbl\u channel\u registers=标签(数字转换器选项卡,text=“channel registers”,font='bold')
    lbl_channel_registers.grid(列=0,行=3,粘性=W)
    帧\通道\寄存器=帧(选项卡\数字化仪)
    frame\u channel\u registers.grid(列=0,行=4)
    btn\u hide\u channel\u registers=按钮(tab\u数字化仪,text=“hide”,fg=“red”,command=lambda:hide\u frame(frame\u channel\u registers))
    btn\u hide\u channel\u registers.grid(列=1,行=3)
    btn_显示_通道_寄存器=按钮(tab_数字化仪,text=“show”,fg=“green”,command=lambda:show_frame(frame_通道_寄存器,0,4))
    btn\u显示\u通道\u寄存器.grid(列=2,行=3)
    ##频道设置-PSD
    def onFrameConfigure(事件):
    ''重置滚动区域以包含内部框架''
    configure(scrollregion=canvas.bbox(“全部”))
    lbl\u PSD\u channel\u registers=标签(帧\u channel\u registers,text=“DPP-PSD registers”)
    lbl\u PSD\u channel\u registers.grid(列=0,行=3,padx=5,粘性=W)
    btn\u hide\u PSD\u channel\u registers=按钮(frame\u channel\u registers,text=“hide”,fg=“red”,command=lambda:hide\u frame(画布))
    btn\u hide\u PSD\u channel\u registers.grid(列=1,行=3)
    btn\u show\u PSD\u channel\u registers=按钮(frame\u channel\u registers,text=“show”,fg=“green”,command=lambda:show\u frame(画布,0,4))
    btn\u显示\u PSD\u通道\u寄存器.grid(列=2,行=3)
    canvas=tk.canvas(frame_channel_寄存器,borderwidth=1,background=“#FF0000”)
    canvas.grid(列=0,行=4)
    frame_PSD_channel_registers=帧(画布,背景=“#0000FF”)
    frame_PSD_channel_registers.grid(列=0,行=0,padx=25,粘性=W)
    myscrollbar=Scrollbar(canvas,orient=“vertical”,command=canvas.yview)
    myscrollbar.grid(列=2,行=0)
    configure(yscrollcommand=myscrollbar.set)
    #canvas.create_window((4,4),window=frame_PSD_channel_寄存器,anchor='nw')
    帧\ PSD \通道\寄存器。绑定(“,onFrameConfigure)
    填充(帧\ PSD \通道\寄存器)
    #这样可以保持窗口打开-必须在末尾
    window.mainloop()
    
    试试看。