Reputation: 1097
I've been following the ttkbootstrap example for creating a collapsible frame widget. This example almost does what I need, but I've noticed the following odd behaviour:
I'd really like to be able to use the example to build my own application, but avoid the behaviour where expanding or collapsing a frame changes the window size. I still need the window itself to be manually resizeable, so disabling window resizing altogether is not an option. Is there any way I can accomplish this?
PS: Below is a slightly modified version of the example code, which can be run without requiring the image assets that the original example uses, if you want to run the example to test it out.
"""
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()
Upvotes: 1
Views: 531
Reputation: 386342
I'd really like to ... avoid the behaviour where expanding or collapsing a frame changes the window size.
You can do that by forcing the window to a specific size. Once the geometry of a window has been set -- whether by the user dragging the window or the program explicitly setting it -- it won't resize when the contents of the window resize.
For example, you can force the window to be drawn, ask tkinter for the window size, and then use the geometry
method to be that same size.
For example, try adding this as the last lines in Application.__init__
:
self.update()
self.geometry(self.geometry())
Upvotes: 2