Home > front end >  How to access value from widgets if the widget was defined in a procedure
How to access value from widgets if the widget was defined in a procedure

Time:12-31

I'm testing out tkinter and trying to have a calculation done on values from a GUI created in a procedure. It works fine if the GUI creation is not in a procedure, but cannot identify the widgets if the widgets are made in a procedure, even if the GUI procedure is defined before the other functions/procedures and called after. Is this impossible or am I doing something wrong?

#TKinter Threading Test

#Importing all relevant tkinter modules
import tkinter as tk
from tkinter import ttk


#Importing threading
from threading import Thread

#Importing queues
import queue

def take_value():
    #Place the input_widget value into the queue
    temp = input_widget.get()
    print(temp)
    #Temporarily pause the entry of new variables
    input_widget.config(state = "disabled")
    output_widget.config(state = "disabled")
    queue_input.put(temp)

def place_value():
    #Check if there is a value in the output queue at all
    if queue_output.empty():
        #print("Output queue is empty")
        temp = "Nothing"
    else:
        temp = queue_output.get()
        #Place the value onto the label
        output_widget.config(text = temp)
        #Re-activate the widgets
        input_widget.config(state = "normal")
        output_widget.config(state = "normal")
    thrdng_root.after(100, place_value)

def calculation_process():
    #Check if there is a value in the input queue at all
    while True:
        if queue_input.empty():
            #print("Input queue is empty")
            temp = "Nothing"
        else:
            temp = queue_input.get()
            new_value = str(float(temp)   1)
            print(new_value)
            queue_output.put(new_value)

def create_GUI():
    #Creating window
    thrdng_root = tk.Tk()
    thrdng_root.geometry("900x900")

    #Creating a queue for values going into the calculation
    queue_input = queue.Queue()
    #Creating a queue for values coming out
    queue_output = queue.Queue()

    #Creating grid columns
    thrdng_root.columnconfigure(0, weight = 3)
    thrdng_root.columnconfigure(1, weight = 7)
    thrdng_root.columnconfigure(2, weight = 3)

    #Creating grid rows
    thrdng_root.rowconfigure(0, weight = 5)
    thrdng_root.rowconfigure(1, weight = 1)
    thrdng_root.rowconfigure(2, weight = 5)
    thrdng_root.rowconfigure(3, weight = 5)
    thrdng_root.rowconfigure(4, weight = 5)

    #Creating entry widget for the user to input a value
    input_widget = ttk.Entry(thrdng_root)
    input_widget.grid(column = 1, row = 0)

    #Creating the output widget
    output_widget = ttk.Label(thrdng_root, background = "#FFFFFF")
    output_widget.grid(column = 1, row = 2)

    place_value()

    #Creating the button that submits the data to the loop
    submit_widget = ttk.Button(thrdng_root, text = "Calculate", command = take_value)
    submit_widget.grid(column = 1, row = 3)

    #Setting the function as a thread
    calc_thread = Thread(target = calculation_process)

    #Starting the thread so that the two indefinite loops can go on without blocking each other
    calc_thread.start()

    #Starting the indefinite GUI loop
    thrdng_root.mainloop()

create_GUI()

CodePudding user response:

This is no different for tkinter widgets as it is for any other python object. You need to save a reference to the widget, and provide a way to access that reference. This is typically done by one of these methods:

  1. save the reference as a global if you aren't using classes
  2. save the reference as an instance variable if you are using classes
  3. pass the reference to the function that needs it.

Since you are not using classes, that eliminates #2. The simplest solution is to use global variables. For every widget that you want to be able to access in a function other than where it was created, you should declare it as global.

For example, if input_widget is one of those widgets you need to use in more than one place, declare it as global in the function where it is defined.

def create_GUI():
    global input_widget
    ...
    input_widget = ttk.Entry(thrdng_root)'
    ...
  • Related