我一直在关注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()