Using a variable from one function onto another - python

I got a problem using variables from one function onto another.
This is my code:
import tkinter as tk
def form ():
textVar = tk.StringVar()
entry0 = tk.Entry(self, textvariable = textVar).pack()
def toPrint():
texto = textVar.get()
print(texto)
def button():
button0 = tk.Button(text="Summit", command = toPrint).pack()
Now the variable being called in toPrint() is local from form(), therefore I can not use it without using global, but that is causing issues with the rest of my code since I'm using form() more than once, is there any other way to solve it?
I would appreciate if the explanation is simple, I'm still a beginner.
I already have searched for this in SO, but I did not manage to understand the answers.

I am a foreigner to English, so firlstly I apologized for my impolite or wrong use of English word. Just want to say I really do not mean it.
And for this question, maybe you could try to put these in the same class. And try to make the variables you want to called several times the attribute of the class.
For example:
class myclass():
def __init__ (self):
self.textVar = tk.StringVar()
self.entry0 = tk.Entry(self, textvariable = textVar).pack()
def toPrint(self):
texto = self.textVar.get()
print(texto)

Related

tkinter: How to access a StringVar and objects from a different class?

I'm having a simple tkinter two frame application with a Label, Entry and Button widget and I want to access a StringVar() of FrameOne with a Entry and Button of FrameTwo.
If have seen a lots of examples of code, but do not get how this is been done in my example below. Many programmers are using a controller. If I would use a controller, I end up from an error to another.
For example:
FirstFrame = FrameOne(mainWindow)`
TypeError: __init__() missing 1 required positional argument: 'controller'
Which I completely understand, because I do not pass anything into the new 'controller' class argument when calling the Frame class. But I do not know what I should pass into this to solve it. Perhaps it is also caused by the lack of knowledge of using class variables (any literature tips are welcome).
The same counts for the solution to inherit FrameOne into FrameTwo. I bump into the same amount of errors applying to my code.
Another thing is that many programmers have examples of two frames that are not visible at the same time, while in my example I have two frames underneath each other at the same time.
An different related issue that I have is, what if the label widget of FrameOne was a Text widget? How do I access the widget from FrameTwo.
I could make it work with globals, but I do not want to use such writing and I will keep the access widget problem anyhow.
Please find my code below:
import tkinter as tk
class AppWindow():
def __init__(self, master):
self.master = master
master.title("Test Application")
master.geometry("1060x680")
master.grid_propagate(False)
class FrameOne(tk.Frame):
def __init__(self, parent):
super().__init__()
self["borderwidth"]=5
self["relief"]="ridge"
self.LabelText = tk.StringVar()
self.LabelText.set("It is not working yet")
self.testlabel = tk.Label(self, textvariable=self.LabelText)
self.testlabel.grid(row=1, column=1)
class FrameTwo(tk.Frame):
def __init__(self, parent):
super().__init__()
self["borderwidth"]=5
self["relief"]="ridge"
self.testentry = tk.Entry(self)
self.testentry.insert("end", "This should be working")
self.testentry.grid(row=1,column=1)
self.testbutton = tk.Button(self, text="Test the label", command=self.updatelabel)
self.testbutton.grid(row=1,column=2)
def updatelabel(self):
FrameOne.LabelText.set(self.testentry.get()) #HOW TO FIX THIS CODE THE RIGHT WAY?
#Create a window as defined in the AppWindow class
mainWindow = AppWindow(tk.Tk())
#Create a Frame as defined in class FrameOne
FirstFrame = FrameOne(mainWindow)
FirstFrame.grid(row=0, column=0) #Positioning Frame on Window
#Create a Frame as defined in class FrameOne
SecondFrame = FrameTwo(mainWindow)
SecondFrame.grid(row=1, column=0) #Positioning Frame on Window
Like with any python object, you access an attribute of an object using a reference to the object.
In your case, updatelabel should look like this:
def updatelabel(self):
FirstFrame.LabelText.set(self.testentry.get())
Note: your use of uppercase characters for instance variables makes your code much harder to comprehend. I recommend following the naming guidelines in PEP8.

python calling similar variables

I have a big problem using tkinter with self here is my code
Could people please give an answer, thanks! The error I get is something like,self could not be given a variable outside a function.
from tkinter import *
root = Tk()
class start():
global self
self = root
def __init__():
self.title('__init__')
self.geometry('300x300')
__init__(self)
class window_extra():
def canvas(self):
global self
selfc = Canvas(self, bg='black').pack()
canvas(self)
self.mainloop()
Thanks!
You should not use self as a variable name as it is used to specify if something is an attribute of the instance of the class.
You do not need to use global in classes either as class attributes are used in most cases when dealing with variables that are needed through the class.
Judging by the code you have shown I think you are trying to do something like this:
from tkinter import *
class start():
def __init__(self, root):
self.master = root
self.master.title('__init__')
self.master.geometry('300x300')
Canvas(self.master, bg='black').pack()
root = Tk()
start(root)
root.mainloop()
However I believe you are struggling with the OOP method of programing and I would suggest to not use OOP to start with if this is the case.
Maybe take a few tutorials on youtube or hit up Codecadamy.
In response to your comments:
In my Opinion using init properly is a bad idea. I use it as a regular def. I doesn't matter if I use self global, unless the function/class variable is called self.
I respect the proper use of init, but I just find the whole thing with, init and self.master I just don't get any of it!
Lack of understanding a thing does not mean said thing is bad. The use of self.master is there to provide a class attribute that ties back to the root Tk() variable. This allows any method within the class to interact with the instance of Tk(). I can't speak to other programing languages but the use of self is a very important in OOP for python. It may not be 100% required to reserve self for referencing to either the instance of the object or the class attribute but it is the accepted and known use of self and really should not be changed/overwritten.
I restructured for some simplicity, but I think that you need a better understanding of objects in Python before going too much further down the GUI route. I think that you mean something like this:
from tkinter import *
# creates a subclass of Tk() called 'Application'; class names by convention
# use CamelCase; best to stick with convention on this one
class Application(tkinter.Tk):
# you don't have to create an explicit invocation of '__init__', it
# is automatically run when you instantiate your class (last line)
def __init__():
super().__init__() # initialize the super class (the 'tkinter.Tk()')
self.title('__init__') # use 'self' to refer to this object - do not declare it as global! it is only valid within the object!
self.geometry('300x300')
self.my_canvas = tkinter.Canvas(self, bg='black') # save an instance of your canvas for easy reference later
self.my_canvas.pack() # pack as a separate step (only required if you plan to use the canvas later... or ever)
self.mainloop() # begin the tkinter loop
# this 'if __name__ ...' is a good idea in most cases, allows you to import `Application` into other
# files without actually running it unless you want to from that other file
if __name__ == '__main__':
Application() # start your class

Calling a function from a checkbox issues

So I'm really fresh into python and perhaps in over my head. I have created a tkinter checkbox inside the mainloop of my gui that is to call a function outside (aulocale1). When clicking the checkbox I get the global name aulocale1 is not defined error. I know this is easily resolved but I've tried googling it and the results don't really make sense. My apologies for the post as I know its something silly.
aulocale = IntVar()
aucheck = Checkbutton(self.master, variable=aulocale, onvalue=1, offvalue=0, text="AU",command=aulocale1)
aucheck.pack(in_=top, side=LEFT)
Function :
def aulocale1(self,master):
self.master.base.replace = "http://www.adidas.com.au/on/demandware.store/Sites-adidas-AU-Site/en_AU"
self.master.replace = ('','AU')
self.master.headers = ('REPLACETHISPLIZZZ','en-AU,en;q=0.8')
It looks like aulocale1 is not global function but method in class so you need self
command=self.aulocale1
if this method and checkbox are in the same class
Or
command=some_object.aulocale1
if method is in different object some_object

In Python, how to make "class" (when passed as a parameter) work the same as "class.attribute"?

So, I am currently making a custom Tkinter module/API mainly just so I can get a better understanding of Tkinter, but I've run into a problem. Suppose I have the following code:
import Tkinter as tk
Class Window(object): # Equivalent of Tkinters Tk() in my module
def __init__(self):
self.root = tk.Tk()
...
Class Label(object): # Equivalent of Tkinters label widget in my module
def __init__(self, master):
self.label = tk.Label(master, text="Hello world!")
...
How can I make it so when I'm creating a label widget, I may do
master = Window()
label = Label(master)
Instead of having to do
master = Window()
label = Label(master.root)
I know I can inherit tk.Tk into my window class, but I'm just curious if there's a different way of doing it. I've done some research and it seems it may have something to do with one of the built-in methods with the leading and trailing double underscores (not sure what they're called), but I don't know what most of those do.
P.S. Sorry for bad title, wasn't sure how to describe it in a short sentence :P
You can write:
self.label = tk.Label(master.root, text="Hello world!")
But as Brian and Paul said, inherit from tk.Tk is the best thing to do.

Tkinter - Entry .get() from another class

i've recently come across a problem thats bugging me with the tkinter entry .get() function, I have put together an example code so you can see what i'm trying to do, I have two classes, a class for each window. In the first window(main window) I have an entry box, in the second window I am attempting to get the entry box text from the first window.
Here's the code: (Trying to get entry box info from the first class in the second class)
from Tkinter import *
class window_1(object):
def __init__(self):
self.app = Tk()
self.app.title("Window One")
def entrybox(self):
self.ent = Entry(self.app) #This is the text i'm trying to get in 2nd class
def button(self):
def ODV(self):
class window_2(object):
def __init__(self):
self.app2 = Tk()
self.app2.title("Window Two")
def labels(self):
self.label_0 = Label(self.app2, text = "Name: ")
def info(self):
self.fetch_name = self.ent.get()#Here is my problem
def gridder(self):
self.label_0.grid(row = 0, column = 0)
self.fetch_name.grid(row = 0, column = 1)
rooter = window_2()
rooter.labels()
rooter.info()
rooter.gridder()
open_data_viewer = lambda: ODV(self)
self.but = Button(self.app, text = "Save", command = open_data_viewer)
def packer(self):
self.ent.pack(anchor = W)
self.but.pack(anchor = W)
def App_Runner(self):
self.app.mainloop()
root = window_1()
root.entrybox()
root.button()
root.packer()
root.App_Runner()
Your first problem is that you're creating more than one instance of Tk. You can't do that, tkinter isn't designed to work that way. If you want multiple windows, create instances of Toplevel. A tkinter program should always have exactly one instance of Tk, exactly one call to mainloop, and there should be little to no code following the call to mainloop.
Second, there is absolutely no value in embedding the definition of a class inside a function. Move it out, it will make your code easier to understand, and easier to write and maintain.
Third, for an instance of one object to access a method on another object, the first object needs to know about the second object or needs to know about a central "controller" object. This isn't a tkinter problem, it's a normal thing to consider when writing OO code.
From a practical standpoint, you need to pass in a reference either to the entry widget, or the object that contains the entry widget, when you create the second object. For example:
class window_2(object):
def __init__(self, other):
...
self.other = other
...
def info(self):
self.fetch_name = self.other.ent.get()
...
rooter = window_2(self) # pass "self" to the new object
This produces a tight coupling between the two objects -- the second object knows about the inner workings of the first object. This is not very good design, though for very, very simple programs it's not so bad. The problem is this: if you change the layout of the first widget, perhaps renaming "self.ent" to "self.some_other_frame.ent", you have to modify the other class too.
A better solution is to define in your first class a function that gets it's own value. Of course, ent serves that purpose, but again, that is a tight coupling. better to have a helper function:
class window_1(object):
...
def get_string(self):
return self.ent.get()
class window_2(object):
def info(self):
self.fetch_name = self.other.get_string()
This still has a loose coupling, but one that is much easier to manage because the coupling isn't tied to the specific internal layout and names of the first window. You can change the widgets all you want, as long as you continue to provide a get_string method that does what the other class expects. Your first class is providing a contract to the second class: a promise that no matter how else the window may change over time, it promises to provide this interface.

Categories

Resources