Search code examples
python-3.xtkinterttk

How to define specific commands for each button included in each pane of a PanedWindow?


I want to create a PanedWindow with variable number of panes which every one of these panes includes a label and a button. Pressing a button in a pane should write a messege to the corresponding label in that pane. I tried this code:

from tkinter import *
from tkinter import ttk

n = 5
root = Tk()
root.geometry('250x500+100+100')

p = ttk.Panedwindow(root, orient=VERTICAL)
p.grid(column=0, row=0, sticky=(N, S, W, E))

for i in range(n):
    pane = ttk.Labelframe(p, width=25, borderwidth=0)
    p.add(pane)
    def writeToLabel():
        paneLabel.config(text='This is Pane number %d' %(i+1))
    paneLabel = ttk.Label(pane, width=20, relief='solid')
    paneButton = ttk.Button(pane, text='Press', command=writeToLabel)
    paneButton.grid(column=0, row=0, padx=5)
    paneLabel.grid(column=1, row=0, padx=5)

root.rowconfigure(0, weight=1)

root.mainloop()

But no matter which button is pressed the label in the last row is set with the message.

I would be grateful if somebody could help me to fix the problem.


Solution

  • I think this is the sort of thing you are looking for:

    from tkinter import *
    from tkinter import ttk
    
    n = 5
    root = Tk()
    root.geometry('250x500+100+100')
    
    p = ttk.Panedwindow(root, orient=VERTICAL)
    p.grid(column=0, row=0, sticky=(N, S, W, E))
    
    
    def writeToLabel(pl, i):
        pl.config(text='This is Pane number %d' %(i+1))
    
    for i in range(n):
        pane = ttk.Labelframe(p, width=25, borderwidth=0)
        p.add(pane)
        paneLabel = ttk.Label(pane, width=20, relief='solid')
        paneButton = ttk.Button(pane, text='Press', command=lambda pl=paneLabel, i=i: writeToLabel(pl, i))
        paneButton.grid(column=0, row=0, padx=5)
        paneLabel.grid(column=1, row=0, padx=5)
    
    root.rowconfigure(0, weight=1)
    
    root.mainloop()
    

    Your current method does not work as the definition of writeToLabel will use the last value of paneLabel and i. You instead need to pass a reference to the label and the value of i using a lambda function. The pl=paneLabel and i=i parts of the lambda function are explained here.