Tkinter - я создал пользовательский класс кадров с прокруткой.Возможно ли, чтобы он автоматически вызывал функцию при добавлении к ней ребенка? - PullRequest
0 голосов
/ 10 апреля 2019

Я создаю собственный виджет tkinter (ScrollFrame) для создания прокручиваемого фрейма, используя ответ на этот вопрос: Полоса прокрутки Tkinter для фрейма

Все работает нормально, но мне приходится вызывать функцию «ConfigureCanvas» каждый раз, когда в ScrollFrame добавляется новый виджет, чтобы изменить размер области прокрутки. Существуют ли какие-либо привязки событий, которые я мог бы использовать, которые будут вызываться, когда новый виджет упакован / размещен / помещен в кадр прокрутки?

например:

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 голосов
/ 10 апреля 2019

Одним из решений является использование события 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]))
...