1

我一直在关注ttkbootstrap 示例来创建可折叠框架小部件。这个例子几乎可以满足我的需要,但我注意到以下奇怪的行为:

  • 如果您运行示例并且不调整窗口大小,则折叠或展开框架会更改整个窗口的大小。
  • 如果您运行该示例并手动调整窗口大小,折叠或展开框架将不再更改窗口大小。

我真的很希望能够使用该示例来构建我自己的应用程序,但要避免展开或折叠框架会改变窗口大小的行为。我仍然需要手动调整窗口本身的大小,因此完全禁用窗口调整大小不是一种选择。有什么办法可以做到这一点吗?

PS:以下是示例代码的略微修改版本,如果您想运行示例进行测试,则无需原始示例使用的图像资源即可运行。

"""
    Author: Israel Dryer
    Modified: 2021-05-03
"""
import tkinter
from tkinter import ttk
from ttkbootstrap import Style


class Application(tkinter.Tk):

    def __init__(self):
        super().__init__()
        self.title('Collapsing Frame')
        self.style = Style()

        cf = CollapsingFrame(self)
        cf.pack(fill='both')

        # option group 1
        group1 = ttk.Frame(cf, padding=10)
        for x in range(5):
            ttk.Checkbutton(group1, text=f'Option {x+1}').pack(fill='x')
        cf.add(group1, title='Option Group 1', style='primary.TButton')

        # option group 2
        group2 = ttk.Frame(cf, padding=10)
        for x in range(5):
            ttk.Checkbutton(group2, text=f'Option {x+1}').pack(fill='x')
        cf.add(group2, title='Option Group 2', style='danger.TButton')

        # option group 3
        group3 = ttk.Frame(cf, padding=10)
        for x in range(5):
            ttk.Checkbutton(group3, text=f'Option {x+1}').pack(fill='x')
        cf.add(group3, title='Option Group 3', style='success.TButton')



class CollapsingFrame(ttk.Frame):
    """
    A collapsible frame widget that opens and closes with a button click.
    """

    ARROW_RIGHT = "\u2b9a"
    ARROW_DOWN = "\u2b9b"

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.columnconfigure(0, weight=1)
        self.cumulative_rows = 0

    def add(self, child, title="", style='primary.TButton', **kwargs):
        """Add a child to the collapsible frame

        :param ttk.Frame child: the child frame to add to the widget
        :param str title: the title appearing on the collapsible section header
        :param str style: the ttk style to apply to the collapsible section header
        """
        if child.winfo_class() != 'TFrame':  # must be a frame
            return
        style_color = style.split('.')[0]
        frm = ttk.Frame(self, style=f'{style_color}.TFrame')
        frm.grid(row=self.cumulative_rows, column=0, sticky='ew')

        # header title
        lbl = ttk.Label(frm, text=title, style=f'{style_color}.Invert.TLabel')
        if kwargs.get('textvariable'):
            lbl.configure(textvariable=kwargs.get('textvariable'))
        lbl.pack(side='left', fill='both', padx=10)

        # header toggle button
        btn = ttk.Button(frm, text=self.ARROW_DOWN, style=style, command=lambda c=child: self._toggle_open_close(child))
        btn.pack(side='right')

        # assign toggle button to child so that it's accesible when toggling (need to change image)
        child.btn = btn
        child.grid(row=self.cumulative_rows + 1, column=0, sticky='news')

        # increment the row assignment
        self.cumulative_rows += 2

    def _toggle_open_close(self, child):
        """
        Open or close the section and change the toggle button image accordingly

        :param ttk.Frame child: the child element to add or remove from grid manager
        """
        if child.winfo_viewable():
            child.grid_remove()
            child.btn.configure(text=self.ARROW_RIGHT)
        else:
            child.grid()
            child.btn.configure(text=self.ARROW_DOWN)


if __name__ == '__main__':
    Application().mainloop()

4

1 回答 1

2

我真的很想......避免展开或折叠框架改变窗口大小的行为。

您可以通过将窗口强制为特定大小来做到这一点。一旦设置了窗口的几何形状——无论是通过用户拖动窗口还是程序明确设置它——当窗口的内容调整大小时,它不会调整大小。

例如,您可以强制绘制窗口,向 tkinter 询问窗口大小,然后使用该geometry方法使其大小相同。

例如,尝试将其添加为最后一行Application.__init__

self.update()
self.geometry(self.geometry())
于 2021-05-04T15:35:55.733 回答