首页 > 解决方案 > 处理 tkinter 框架中的视觉溢出?

问题描述

我正在编写一个添加滚动框架的类。它检测框架的内容何时超过其高度,然后配置滚动条。问题是当我向下滚动时,框架中的项目会滚动到框架顶部之外并出现在其上方。

我已经使用普通标签对其进行了测试,并且效果很好,但是我使用的是具有一些嵌套框架的类对象,并且子对象显示在滚动框架上方。

这是给我带来问题的代码的要点(请注意,布局与整个项目不匹配。我将此作为ScrollFrame()课程的参考。)

只需运行它,按下按钮,然后向下滚动就会告诉你它有什么问题。


import tkinter as tk
import tkinter.simpledialog as sd


class ScrollFrame(tk.Frame):

    def __init__(self, master):

        tk.Frame.__init__(self, master)


        ### setting up the objects used ###
        self.canvas = tk.Canvas(master)
        self.frame = tk.Frame(self.canvas)
        self.scrollbar = tk.Scrollbar(master, orient = 'vertical',
                                      command = self.canvas.yview)


        ### scrollbar moves with current canvas scrollamount ###
        self.canvas.configure(yscrollcommand = self.scrollbar.set)


        self.scrollbar.pack(side = 'right', fill = 'y')
        self.canvas.pack(side = 'left', fill = 'both', expand = True)


        ### creating frame to pack widgets onto ###
        self.canvas.create_window((4, 4), window = self.frame,
                                  anchor = 'nw', tags = 'self.frame')


        ### setting scrollbar height on load ###
        self.frame.bind('<Configure>', self.frameConfig)


        ### scroll when a user's mouse wheel is used inside the canvas ###
        def scrollCanvas(event):
            self.canvas.yview_scroll(-1*(event.delta//120), 'units')
        self.canvas.bind('<MouseWheel>', scrollCanvas)


    ### set the scrollregion of the canvas ###
    def frameConfig(self, event):
        self.canvas.configure(scrollregion = self.canvas.bbox('all'))

class OptionSet(tk.Frame):

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

        super().__init__()
        self.all = tk.Frame(master)
        self.all.configure(bd = 1, relief = 'solid')


        # independent label
        self.text = '' if not kwargs['text'] else kwargs['text']
        self.label = tk.Label(text = self.text)


        # list of all buttons
        self.buttons = tk.Frame()

        buttons = [] if not kwargs['buttons'] else kwargs['buttons']
        self.button_list = []

        if buttons:
            for button in buttons:
                self.button_list.append(
                        tk.Button(self.buttons, text = button)
                    )

        self.style()


    def style(self, default = 1, **kwargs):

        if default:
            self.label.pack(in_ = self.all, side = 'left')

            for button in self.button_list:
                button.pack(side = 'left')

            self.buttons.pack(in_ = self.all, side = 'right')


root = tk.Tk()

list_items = []
current = {
    'month': 'August'
    # ...
}

def btn_fcn(num):

        for i in list_items:
            i.grid_forget()

        '''
        # get event as input
        event = sd.askstring('Event Input',
            f"What is happening on {current['month']} {num}?")

        # insert new list_item
        list_items.append(OptionSet(event_list.frame, text = event,
                          buttons = ['Edit', 'Delete']))
        print(event)
        '''

        for i in range(10):
            list_items.append(OptionSet(event_list.frame, text = 'test',
                                        buttons = ['Edit', 'Delete']))

        for i in list_items:
            i.all.grid(sticky = 'we')

tk.Button(root, text = 'Add', command = lambda: btn_fcn(22)).pack()
event_list = ScrollFrame(root)
event_list.pack()

root.mainloop()

我希望按钮和标签在 ScrollFrame 之外被切断。我不知道它们是否从框架或画布溢出,但如果一切按计划进行,它们应该正常切断。

谢谢。

标签: pythontkinter

解决方案


问题是您对创建小部件的位置非常草率。例如,您不是将画布和滚动条放在 ScrollFrame 中,而是将其放在master. 中定义的每个小部件都需要ScrolLFrame在.selfself

这同样适用OptionSet- 您将内部框架 ( self.all) 和其他小部件放入master而不是放入OptionSet自身。

我的建议是暂时删除所有OptionSet代码(或者干脆不使用它),而是只在滚动框架中添加标签。专注于在没有将自定义类添加到自定义类的复杂性的情况下使其正常工作。一旦您能够只滚动标签,您就可以在OptionSet代码中重新添加。


推荐阅读