So I was messing around with Tkinter, and I was wondering, is there an easy way to wipe whatever widgets you currently have 'packed' and show a new layout?

So, if my fist screen has a button, I want a whole new layout to come up when the user hits that button, but I'd like to keep it in the same tk window.

Additionally, how do I pass arguments with 'command' options, because this doesn't work:

button1 = Button(root,text = 'Press me!',command = say('you pressed me!'))

EDIT: lol, just realized the title is 'Multible', should be Multiple.

Recommended Answers

All 3 Replies

Tkinter's 'command=' accepts a function reference not a function call, so you have to use a callback arrangement to pass arguments:

# Tkinter example showing several ways for command to pass an argument

import Tkinter as tk

# use a closure
def closure_callback(val):
    def closure():
        root.title(val)
    return closure

def change_title(val):
    root.title(val)

# note in this case callback is onButton3
def curry_callback(callback, *args, **kwargs):
    """adds arguments to callback functions"""
    def do_call():
        return callback(*args, **kwargs)
    return do_call

def onButton3(val):
  root.title(val)

root = tk.Tk()

s1 = "passing a string to the title using a closure_callback"
button1 = tk.Button(root, text=s1, command=closure_callback(s1))
button1.pack(padx=100, pady=10)

s2 = "passing a string to the title using a lambda_callback"
lambda_callback = lambda: change_title(s2)
button2 = tk.Button(root, text=s2, command=lambda_callback)
button2.pack(padx=100, pady=10)

s3 = "passing a string to the title using a curry_callback"
button3 = tk.Button(root, text=s3, command=curry_callback(onButton3, s3))
button3.pack(padx=100, pady=10)

root.mainloop()

Also note that Python25 has a class 'partial' that works much like 'curry'.

To destroy widgets that belong together, put them on a frame:

# a look at Tkinter's frame widget
# a frame wraps the widgets put on it

from functools import partial  # needs Python25 or higher
import random
import Tkinter as tk

def make_frame(parent, frame=None, color='white'):
    global count
    count += 1
    parent.title("Frame %d" % count)
    if frame:
        # destroy any old frame and its widgets
        frame.destroy()
    # now create a new frame
    frame = tk.Frame(top, bg=color)
    frame.pack(expand="true")

    # give the frame some widgets
    b1 = tk.Button(frame, text=color+"_button1")
    b2 = tk.Button(frame, text=color+"_button2")
    b3 = tk.Button(frame, text=color+"_button3")

    color = random.choice(['red', 'green', 'yellow', 'blue', 'cyan'])
    # use partial callback to pass arguments
    par_callback = partial(make_frame, parent, frame, color)
    b4 = tk.Button(frame, text="Create new frame", command=par_callback)

    # you can use pack() for the frame and grid() for its widgets
    b1.grid(row=0, column=0, padx=15, pady=5)
    b2.grid(row=1, column=1, padx=15, pady=5)
    b3.grid(row=2, column=2, padx=15, pady=5)
    b4.grid(row=3, column=3)
    return frame

top = tk.Tk()
count = -1
# initial dummy
frame1 = make_frame(top)

frame2 = make_frame(top, frame1)

top.mainloop()

Both of these worked!

Thanks so much!

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.