Home > Blockchain >  How to change global variable in a file by pressing tkinter button in another file?
How to change global variable in a file by pressing tkinter button in another file?

Time:10-18

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


PEP 20 -- Python Zen

... 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)
  • Related