Tkinter-我创建了一个自定义的可滚动框架类。在添加子功能后,它是否可以自动调用函数?

时间:2019-04-10 19:12:25

标签: python tkinter tkinter-canvas

我使用以下问题的答案制作了一个自定义tkinter小部件(ScrollFrame)以制作可滚动框架:Tkinter scrollbar for frame

一切正常,但每次将新的小部件添加到ScrollFrame中时,我都必须调用“ ConfigureCanvas”函数,以调整滚动区域的大小。当将新的小部件打包/网格化/放置到“滚动框架”中时,是否可以调用任何事件绑定?

例如:

class ScrollFrame(Frame):
    '''
    '''
    self.packFrame.bind('<NewChildWidgetAdded>', self.ConfigureCanvas)
    '''
    '''

exampleLabel = Label(packFrame, text='Hello')
exampleLabel.pack() # activate the "NewChildWidgetAdded" event?

这是工作代码(python 3+)。我创建了一个循环,该循环创建了50个标签,可以给我一些滚动的内容。

import tkinter
from tkinter import Tk, Frame, filedialog, Button, Listbox, Label, Entry, Text, Canvas, Scrollbar, Radiobutton, Checkbutton, Menu, IntVar, StringVar, BooleanVar, Grid, OptionMenu, Toplevel, ALL, CURRENT, END
#imported more than i needed, copied from other code where this is all used. 

class ScrollFrame(Frame):
    def __init__(self, frame, *args, **kwargs):
        Frame.__init__(self, frame, *args, **kwargs)

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

        self.vScroll = Scrollbar(self, orient='vertical')
        self.vScroll.grid(row=0, column=1, sticky='wens')
        self.hScroll = Scrollbar(self, orient='horizontal')
        self.hScroll.grid(row=1, column=0, sticky='wens')

        self.canvas = Canvas(self, bd=0, highlightthickness=0, xscrollcommand=self.hScroll.set, yscrollcommand=self.vScroll.set, bg='green')
        self.canvas.grid(row=0, column=0, sticky='wens')
        self.vScroll.config(command=self.canvas.yview)
        self.hScroll.config(command=self.canvas.xview)

        self.packFrame = Frame(self.canvas, bg='blue')
        self.packWindow = self.canvas.create_window(0,0, window=self.packFrame, anchor='nw')

    def ConfigureCanvas(self):
        self.packFrame.update_idletasks()
        size = (self.packFrame.winfo_reqwidth(), self.packFrame.winfo_reqheight())
        self.canvas.config(scrollregion=(0,0,size[0], size[1]))

mw = Tk()

scrollCavnas = ScrollFrame(mw)
scrollCavnas.pack(side='right', fill='both', expand='yes')
scrollFrame = scrollCavnas.packFrame

temp = 0
while temp < 50:
    Label(scrollFrame, text=temp).grid(row=temp, column=temp)
    temp += 1
    scrollCavnas.ConfigureCanvas() # don't want to have to call this every time a new widget is added.

mw.mainloop()

我尝试过:

self.packFrame.bind('<map>', self.ConfigureCanvas)

但是,看起来只有在创建ScrollFrame时才会调用此函数,而不是在向ScrollFrame添加新的子窗口小部件时调用。

我查看了文档(http://tcl.tk/man/tcl8.5/TkCmd/bind.htm#M13),但没有发现任何可以做我想做的事情。

1 个答案:

答案 0 :(得分:0)

一种解决方案是使用Configure事件。缺点是每次滚动小部件时都会调用此方法。

self.packFrame.bind('<Configure>', self.ConfigureCanvas)

def ConfigureCanvas(self, event=None):
    self.packFrame.update_idletasks()
    size = (self.packFrame.winfo_reqwidth(), self.packFrame.winfo_reqheight())
    self.canvas.config(scrollregion=(0,0,size[0], size[1]))

我至少能够获得部分功能,仅在添加新小部件时才能运行。这似乎很笨拙,我相信只有水平滚动才能使用(可以修改为垂直滚动或双向滚动)。它将所需的宽度与当前滚动区域的大小进行比较,如果它们不同,它将调整滚动区域的大小。

def ConfigureCanvas(self, event=None):
    scrollRegion = self.canvas['scrollregion'].split(' ')
    try:
        scrollRegion = int(scrollRegion[2])
    except IndexError:
        scrollRegion = None
    if self.packFrame.winfo_reqwidth() != scrollRegion:
        self.packFrame.update_idletasks()
        size = (self.packFrame.winfo_reqwidth(), self.packFrame.winfo_reqheight())
        self.canvas.config(scrollregion=(0,0,size[0], size[1]))