Search code examples
pythontkinterttkttkwidgets

Tkinter (Python) how to get values from all Text widgets in a Function


I am building one of my first UIs with Tkinter and ttk and struggle to link one button click event to collect two widget values. I want to create a “settings” menu as a child frame and have a feature to modify and read current values from two Text widgets.

So, I’d like:

  1. Have an ability to add OR remove text from widget.
  2. Using Button click event, collect current widget values and work with them in separate function

With my current approach I am not sure how to read both widgets values (in case user changed them), as “command = lambda” allows me to sent only one argument.

I was thinking to call a function with “GetValues” button click event, but not sure how to access Text widgets from the function.

Here is my code

    from tkinter import *
from tkinter import ttk

# Print  values from both Text Widgets
def getValues():

    print(TextAreaRegion.get("1.0","end-1c"))
    print(TextAreaService.get("1.0", "end-1c"))

#Create a child window for Settings
def openSettingsWindow():
    settingsWindow = Toplevel(root)
    settingsWindow.title("Settings")
    settingsWindow.geometry('640x480+100+100')
    settingsWindow.resizable(False, False)
    Label(settingsWindow, text="Settings").pack()

    frameLeft = ttk.LabelFrame(settingsWindow)
    TextAreaRegion = Text(frameLeft, width=60, height=2, wrap='word')


    frameLeft.pack()
    frameLeft.config(height=400, width=300, relief=RIDGE, padding=(30, 15), text="Settings")

    ttk.Label(frameLeft, text="Regions:").grid(row=0, column=0, sticky='w', padx=5, pady=10)
    ttk.Label(frameLeft, text="Tenants:").grid(row=1, column=0, sticky='w', padx=5, pady=10)

    TextAreaRegion.grid(row=0, column=1, sticky='w')
    TextAreaRegion.insert('1.0 + 2 lines', "RegionOne, RegionTwo")

    TextAreaService = Text(frameLeft, width = 60, height = 2)
    TextAreaService.grid(row=1, column=1, sticky='w')
    TextAreaService.insert('1.0 + 2 lines', "ServiceOne, ServiceTwo")

    #Button
    buttonSave = ttk.Button(frameLeft, text="Get values", command=getValues)
    buttonSave.grid(row=3, column=0, sticky='w', padx=5)

root = Tk()

#Menu bar
root.option_add('*tearOff', False)
menubar = Menu(root)
root.config(menu = menubar)
file = Menu(menubar)
menubar.add_cascade(menu = file, label = 'File')

#Add menu elements
file.add_command(label = 'Settings', command = openSettingsWindow )

root.mainloop( )

I can get a value for one of the widget, if I use lambda, however, I can't use two arguments for lambda:

buttonSave = ttk.Button(frameLeft, text="Get values", command=lambda:print(TextAreaService.get("1.0", "end-1c")))

Solution

  • Here is the working code with a lambda function with multiple arguments.

    from tkinter import *
    from tkinter import ttk
    
    # Print  values from both Text Widgets
    def getValues(region_box, service_box):
        print(region_box.get("1.0","end-1c"))
        print(service_box.get("1.0","end-1c"))
    
    
    #Create a child window for Settings
    def openSettingsWindow():
        settingsWindow = Toplevel(root)
        settingsWindow.title("Settings")
        settingsWindow.geometry('640x480+100+100')
        settingsWindow.resizable(False, False)
        Label(settingsWindow, text="Settings").pack()
    
        frameLeft = ttk.LabelFrame(settingsWindow)
        TextAreaRegion = Text(frameLeft, width=60, height=2, wrap='word')
    
    
        frameLeft.pack()
        frameLeft.config(height=400, width=300, relief=RIDGE, padding=(30, 15), text="Settings")
    
        ttk.Label(frameLeft, text="Regions:").grid(row=0, column=0, sticky='w', padx=5, pady=10)
        ttk.Label(frameLeft, text="Tenants:").grid(row=1, column=0, sticky='w', padx=5, pady=10)
    
        TextAreaRegion.grid(row=0, column=1, sticky='w')
        TextAreaRegion.insert('1.0 + 2 lines', "RegionOne, RegionTwo")
    
        TextAreaService = Text(frameLeft, width = 60, height = 2)
        TextAreaService.grid(row=1, column=1, sticky='w')
        TextAreaService.insert('1.0 + 2 lines', "ServiceOne, ServiceTwo")
    
        #Button - Note you can pass multiple arguments in a lambda function like here
        buttonSave = ttk.Button(frameLeft, text="Get values", command=lambda region_box=TextAreaRegion, service_box=TextAreaService: getValues(region_box, service_box))
        buttonSave.grid(row=3, column=0, sticky='w', padx=5)
    
    
    
    root = Tk()
    
    #Menu bar
    root.option_add('*tearOff', False)
    menubar = Menu(root)
    root.config(menu = menubar)
    file = Menu(menubar)
    menubar.add_cascade(menu = file, label = 'File')
    
    #Add menu elements
    file.add_command(label = 'Settings', command = openSettingsWindow )
    
    root.mainloop( )