[Tkinter] HOW TO: Use Globals In Module ??? - Printable Version +- Python Forum (https://python-forum.io) +-- Forum: Python Coding (https://python-forum.io/forum-7.html) +--- Forum: GUI (https://python-forum.io/forum-10.html) +--- Thread: [Tkinter] HOW TO: Use Globals In Module ??? (/thread-18213.html) |
HOW TO: Use Globals In Module ??? - Webtest - May-09-2019 Esteemed Forum Participants and Lurkers: Platform: Linux Mint 18.3 Mate 64-bit, Python 3.5.2 & Idle3 I am working on a Python 3 program using TKinter which is essentially a keystroke driven state machine. I want to segregate the different states in 'modules'. The 'root' TKinter window is global to the whole program, but I can't seem to make it visible to a module, EXCEPT I CAN pass it to a function in a module as a parameter. How do I make it available to the function as a global object which is what I REALLY want to learn how to do? Main Program: # Module Test for Globals and Modules import tkinter as tk Groot = tk.Tk() # Create the GLOBAL root window Glabel1 = [] # Global Label identifier GCOUNT = 0 # Global Keystroke counter # Pull in the "setup" module import setup # Create and load the display label setup.setup() # ######### Keyboard 'Keypress' event handler ######### def key(event): global GCOUNT GCOUNT += 1 msg = '%d %r %d %d' %(GCOUNT,event.keysym,event.keysym_num,event.state) print(msg) # ####################################################### # Bind the Keypress event to the 'key' event handler Groot.bind_all('<Key>', key) # Exit to the running event-driven app Groot.mainloop()Test Module: # MODULE "setup.py" in moduletest import tkinter as tk # GLOBALS: global Groot global Glabel1 def setup(): # Create and load the display label into the window prompt = ' Press any key ' Glabel1 = tk.Label(Groot, text=prompt, width=len(prompt), bg='yellow') Glabel1.pack() return()Here is the error message: Traceback (most recent call last): File "/media/mint/python/keystroke.py", line 19, in <module> setup.setup() File "/media/mint/python/setup.py", line 18, in setup Glabel1 = tk.Label(Groot, text=prompt, width=len(prompt), bg='yellow') NameError: name 'Groot' is not defined As I mentioned, I can get this to work by passing 'Groot' as a parameter to setup.setup(), but how can I use 'Groot' as a global WITHOUT having to pass it as a parameter? Thank you for any and all comments, suggestions, and assistance in this effort. Blessings in abundance, all the best, & ENJOY! Art in Carlisle, PA USA RE: HOW TO: Use Globals In Module ??? - metulburr - May-09-2019 Without passing as a parameter... i would say to create your Groot within setup directly and pass that back to the main program then. Often you will have a settings file with static data that you import to many modules. You should be cautious to use globals so often. setup.py # MODULE "setup.py" in moduletest import tkinter as tk Groot = tk.Tk() def setup(): # Create and load the display label into the window prompt = ' Press any key ' Glabel1 = tk.Label(Groot, text=prompt, width=len(prompt), bg='yellow') Glabel1.pack() return Grootmain program import setup #<- imports go at top ... #Groot = tk.Tk() # Create the GLOBAL root window Glabel1 = [] # Global Label identifier GCOUNT = 0 # Global Keystroke counter # Create and load the display label Groot = setup.setup() ... RE: HOW TO: Use Globals In Module ??? - Webtest - May-10-2019 Thanks metulburr! Your suggestion looks reasonable and your advice is sound. I did a LOT of searching, and did find MANY caveats regarding Globals. However, I did also find the following ELEGANT and sanctioned solution, which works great for my program: Python Software Foundation Programming FAQ: How do I share global variables across modules? It is very brief and is well worth looking at. Basically, you just put all the Globals in a "config.py" file. That puts them all in a single file in their own namespace ... I use "import config as G", so each Global is "G.name". Without this I would be passing TONS of stuff ... 3 arrays of 65 widgets each, a dictionary of complex dynamic widget formats, and many other variables. Each of the FIVE steps of the State Machine manipulates them differently. # Module config.py Root = [] # Global Window identifier Label1 = [] # Global Label identifier Count = 0 # Global Keystroke counter # Module Test for Globals and Modules import tkinter as tk import config as G import setup G.Root = tk.Tk() # Create the GLOBAL root window # Create and load the display label setup.setup() # ######### Keyboard 'Keypress' event handler ######### def key(event): G.COUNT += 1 msg = '%d %r %d %d' %(G.COUNT,event.keysym,event.keysym_num,event.state) print(msg) # ####################################################### # Bind the Keypress event to the 'key' event handler G.Root.bind_all('<Key>', key) # Exit to the running event-driven app G.Root.mainloop() # MODULE "setup.py" in moduletest import tkinter as tk import config as G def setup(): # Create and load the display label into the window prompt = ' Press any key ' G.Label1 = tk.Label(G.Root, text=prompt, width=len(prompt), bg='yellow') G.Label1.pack() # <-- pack/grid MUST be on separate line !!! returnBlessings in abundance, all the best, & ENJOY! Art in Carlisle, PA USA RE: HOW TO: Use Globals In Module ??? - snippsat - May-10-2019 (May-10-2019, 04:28 AM)Webtest Wrote: I did also find the following ELEGANT and sanctioned solution, which works great for my program:It may work,buy is far from great There is a reason why classes is almost always used and preferred in GUI programming. Then there is no use of Globals , self act like magic transporter of values.So a basic example with a class from doc,if i put in counter as you have it then it look like this. See that there is no Global used to make this counter. import tkinter as tk class Application(tk.Frame): def __init__(self, master=None): super().__init__(master) self.master = master self.button_clicks = 0 self.pack() self.create_widgets() def create_widgets(self): self.hi_there = tk.Button(self) self.hi_there["text"] = "Click me" self.hi_there["command"] = self.say_hi self.hi_there.pack(side="top") self.quit = tk.Button(self, text="QUIT",fg="blue",command=self.master.destroy) self.quit.pack(side="bottom") def say_hi(self): self.button_clicks += 1 print(f"hi there,you have clicked {self.button_clicks} times now") root = tk.Tk() app = Application(master=root) app.mainloop() |