I have 2 python Files, FirstWindowFile
and SecondWindowFile
.
I create one button in 1st and I want, after pressing it, to create
a new window with a button in the 2nd file.
After pressing the button in the 2nd file, I need to change the
value of the global variable in 1st.
FirstWindowFile
code:
import tkinter as tk
from tkinter import*
import SecondWindowFile
root = Tk() # create a main window
root.geometry("750x250")
global myglobal # this is the global i want to change
myglobal = 0
btn1 = tk.Frame(root, borderwidth=5, relief="ridge")
btn1.grid(column=0, row=0)
# when I press this button I send the SecondWindowFile to ChangeValue()
Analyze = tk.Button(btn1, text="Analyze",
command=lambda: SecondWindowFile.ChangeValue()).grid(row=0, column=0)
# myglobal has to take new value (sent from SecondWindowFile) so to
# be used for new calculations
print(myglobal)
root.mainloop()
SecondWindowFile
code:
import tkinter as tk
from tkinter import*
def changeMyNum():
gl=1
# I need this value of gl to be returned to the FirstWindowFile and be the
# new value of global myglobal
def ChangeValue():
secondWindow = Tk() # create a 2nd window
secondWindow.geometry("150x150")
btn2 = tk.Frame(secondWindow, borderwidth=5, relief="ridge") # create a button
btn2.grid(column=0, row=0)
# by pressing the button goes to changeMyNum()
ChangeVal = tk.Button(secondWindow, text="Press to Change Global",
command=lambda: changeMyNum).grid(row=0, column=0)
CodePudding user response:
You can't access global from one file in another. And it is not good idea. You should use variable in an explicit way - if you would use list
, dict
or tk.IntVar
, tk.StringVar
to keep value then you could send it as argument and function could change value in list
, dict
or tk.IntVar
, tk.StringVar
and you could this value in other functions.
tk.IntVar
can be also useful because you can assign it to label and when you change IntVar
then it automatically update value in Label
.
You have to only rembember that IntVar
needs .get()
and .set()
to works with value.
main.py
myglobal = tk.IntVar(value=0) # you have to create after `root`
Button(..., command=lambda:second_window.change_value(myglobal)
second_window.py
def change_value(variable):
Button(..., command=lambda:change_my_num(variable))
def change_my_num(variable):
variable.set( variable.get() 1 )
print(variable.get())
And now you can assing it to Label
to display current value
Label(..., textvariable=myglobal)
Full code:
main.py
import tkinter as tk
#from tkinter import * # PEP8: `import *` is not prefered
import second_window
#
root = tk.Tk() # create a main window
root.geometry("750x250")
myglobal = tk.IntVar(value=0) # you have to create after `root`
btn1 = tk.Frame(root)
btn1.grid(column=0, row=0)
# PEP8: `lower_case_names` for variables
analyze = tk.Button(btn1, text="Analyze", command=lambda:second_window.change_value(myglobal))
analyze.grid(row=0, column=0)
l = tk.Label(btn1, textvariable=myglobal)
l.grid(row=1, column=0)
print(myglobal.get()) # it runs it before `mainloop` starts GUI and shows window - so it is useless.
root.mainloop()
print(myglobal.get()) # it runs it after closing window
second_window.py
import tkinter as tk # PEP8: `import *` is not preferred
def change_my_num(variable): # PEP8: `lower_case_names` for functions
variable.set( variable.get() 1 )
print(variable.get())
def change_value(variable):
second_window = tk.Toplevel() # use `Toplevel to create a 2nd window
b = tk.Button(second_window, text="Press to Change Global", command=lambda:change_my_num(variable))
b.grid(row=0, column=0)
PEP 8 -- Style Guide for Python Code
... Explicit is better than implicit. ...
CodePudding user response:
Here's a more general answer to the problem I think your having:
Starting with the SecondWindowFile
, define a function that creates a GUI that ends itself and returns a variable when a button is pressed.
In FirstWindowFile
define your variable as the return of your SecondWindowFile
function.
Eg:
FirstWindowFile:
global myVar # The variable doesn't have to be global for this to work
def onButtonPress():
myVar = SecondWindowFile.getValue()
SecondWindowFile:
def getValue():
def onButtonPress():
return 'The Value You Want'
getValue()
being the function you created that returns the var
If you need further clarification, please ask!
CodePudding user response:
My answer is very similar to @furas', but illustrates how to define and use a class
to avoid (or at least minimize) using global variables — which won't work for what you want to do anyway. In this case by storing it in a tkinter IntVar
and explicitly passing that as an argument to a function defined in the file of another module.
I've also largely tried to follow PEP 8 - Style Guide for Python Code as he (and I) strongly recommend, especially with respect to those in the naming conventions section (which also apply to module file names).
first_window.py
import tkinter as tk
import second_window as sw
class MyApp:
def __init__(self, master):
self.frame = tk.Frame(master, borderwidth=5, relief="ridge")
self.frame.grid(row=0, column=0)
self.my_var = tk.IntVar(master=master, value=0)
analyze_btn = tk.Button(self.frame, text="Analyze",
command=lambda: sw.change_value(self.my_var))
analyze_btn.grid(row=0, column=0, columnspan=2)
tk.Label(self.frame, text="My var:").grid(row=1, column=0)
tk.Label(self.frame, textvariable=self.my_var).grid(row=1, column=1)
if __name__ == '__main__':
root = tk.Tk() # Create a main window.
root.geometry("750x250")
my_app = MyApp(root)
root.mainloop()
second_window.py
import tkinter as tk
def change_my_num(var):
var.set(var.get() 1) # Increment value in IntVar.
def change_value(var):
second_window = tk.Tk() # Create a 2nd window.
second_window.geometry("150x150")
frame2 = tk.Frame(second_window, borderwidth=5, relief="ridge")
frame2.grid(row=0, column=0)
change_val_btn = tk.Button(frame2, text="Press to Change Global",
command=lambda: change_my_num(var))
change_val_btn.grid(row=0, column=0)
done_btn = tk.Button(frame2, text="Done", command=second_window.destroy)
done_btn.grid(row=1, column=0)