Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Expandable and contracting frame in Tkinter

Does anyone know if there is already a widget/class to handle expanding/contracting a frame based on a toggled button (checkbutton) in tkinter/ttk?

This question stems from my attempt to clean up a cluttered gui that has lots of options categorized by specific actions. I would like something along the lines of:

enter image description here
example found on google

However instead of just text, allow for buttons, entries, any of tkinter's widgets. If this doesn't already exist, would it be possible/useful to create a class that inherits the tkinter Frame:

import tkinter as tk
import ttk

class toggledFrame(tk.Frame):
    def __init__(self):
        self.show=tk.IntVar()
        self.show.set(0)
        self.toggleButton=tk.Checkbutton(self, command=self.toggle, variable=self.show)
        self.toggleButton.pack()
        self.subFrame=tk.Frame(self)

    def toggle(self):
        if bool(self.show.get()):
            self.subFrame.pack()
        else:
            self.subFrame.forget()

Note: this code is untested, just presenting concept

like image 593
Onlyjus Avatar asked Oct 30 '12 14:10

Onlyjus


People also ask

What is expand in tkinter?

The pack() fill option is used to make a widget fill the entire frame. The pack() expand option is used to expand the widget if the user expands the frame. fill options: NONE (default), which will keep the widget's original size. X, fill horizontally.

How do you toggle frames in tkinter?

One way to switch frames in tkinter is to destroy the old frame then replace it with your new frame. I have modified Bryan Oakley's answer to destroy the old frame before replacing it. As an added bonus, this eliminates the need for a container object and allows you to use any generic Frame class.

What is the difference between tkinter window and frame?

Tk creates the root window. Every tkinter application must have a root window. When you instantiate it you also create a tcl interpreter that is used by tkinter. Frame is just a widget, designed to be a container for other widgets.

What is frame used for in tkinter?

The Frame widget is very important for the process of grouping and organizing other widgets in a somehow friendly way. It works like a container, which is responsible for arranging the position of other widgets. It uses rectangular areas in the screen to organize the layout and to provide padding of these widgets.


1 Answers

I am actually surprised at how close I was to getting functioning code. I decided to work on it some more and have develop a simple little class to perform exactly what I wanted (comments and suggestions on the code are welcome):

import tkinter as tk
from tkinter import ttk 


class ToggledFrame(tk.Frame):

    def __init__(self, parent, text="", *args, **options):
        tk.Frame.__init__(self, parent, *args, **options)

        self.show = tk.IntVar()
        self.show.set(0)

        self.title_frame = ttk.Frame(self)
        self.title_frame.pack(fill="x", expand=1)

        ttk.Label(self.title_frame, text=text).pack(side="left", fill="x", expand=1)

        self.toggle_button = ttk.Checkbutton(self.title_frame, width=2, text='+', command=self.toggle,
                                            variable=self.show, style='Toolbutton')
        self.toggle_button.pack(side="left")

        self.sub_frame = tk.Frame(self, relief="sunken", borderwidth=1)

    def toggle(self):
        if bool(self.show.get()):
            self.sub_frame.pack(fill="x", expand=1)
            self.toggle_button.configure(text='-')
        else:
            self.sub_frame.forget()
            self.toggle_button.configure(text='+')


if __name__ == "__main__":
    root = tk.Tk()

    t = ToggledFrame(root, text='Rotate', relief="raised", borderwidth=1)
    t.pack(fill="x", expand=1, pady=2, padx=2, anchor="n")

    ttk.Label(t.sub_frame, text='Rotation [deg]:').pack(side="left", fill="x", expand=1)
    ttk.Entry(t.sub_frame).pack(side="left")

    t2 = ToggledFrame(root, text='Resize', relief="raised", borderwidth=1)
    t2.pack(fill="x", expand=1, pady=2, padx=2, anchor="n")

    for i in range(10):
        ttk.Label(t2.sub_frame, text='Test' + str(i)).pack()

    t3 = ToggledFrame(root, text='Fooo', relief="raised", borderwidth=1)
    t3.pack(fill="x", expand=1, pady=2, padx=2, anchor="n")

    for i in range(10):
        ttk.Label(t3.sub_frame, text='Bar' + str(i)).pack()

    root.mainloop()

This code produces:
enter image description here

like image 110
Onlyjus Avatar answered Oct 05 '22 23:10

Onlyjus