Tkinter entry widget get is undefined, not updating to my main function, - python

i'm following a few different guides to re-learn Tkinter by writing a little application that grabs stock prices. My issue that I am up a wall against is calling the .get() method from my entry widget variable. I've seen a couple other suggestions to put all the widget creating inside a function and then call the function in the init method, however I'm getting the same error, even when using the self argument in front of my entry variables. I know it's an issue with the way i'm passing data from function to function, but I can't wrap my head around it. Here's the code, sorry for the wall of text:
class MyApp:
def __init__(self, parent):
self.myParent = parent
self.myContainer1 = Frame(parent)
self.myContainer1.pack()
self.createWidgets()
button1 = Button(self.myContainer1, command = self.button1Click)
button1.configure(text = "get quote")
button1.pack()
def createWidgets(self):
root.title("Stock App")
self.symbol = Entry(self.myContainer1)
self.symbol.pack()
self.symbol.focus_set()
def button1Click(self):
stock = symbol.get()
print stock
I've taken it down to simplest form even and just had the button1Click call a callback function-
def button1Click(self):
print callback()
def callback():
print symbol.get()
This returns the exact same error:
NameError: global name 'symbol' is not defined
Is it getting destroyed too early? how do I fix this?
I've referenced multiple documents for tkinter and have seen some great fixes but none are extensible, or um unable to see how they relate to me using it inside of an object.
Thanks in advance for the help.

As far as I can tell inside of your button1Click method you need to add self as in:
def callback():
print self.symbol.get()

You're missing self. to make the callback:
def callback():
print self.symbol.get()
instead.

Related

Getters in python, tkinter

I need access to information from my class "makeEntry" precisely textvariables. I tried make get function but i read that in python it's not necessary.
def temp():
print(e_full_name.get_text())
class makeEnetry:
def __init__(self, i_parent, i_width, i_row, i_column, i_text):
test.set(i_text)
test = StringVar()
entry = Entry(master = i_parent, width = i_width, textvariable = test)
entry.grid(row = i_row, column = i_column, padx = 5, pady =5 )
def get_text(self):
return self.test.get()
I tried to move my test = StringVar() above function, just in class to refer to it in another function but it doesn't work. I'm newbie in python and I have no idea what I have done wrong.
def temp():
print(e_full_name.get_text())
class makeEnetry:
test = StringVar()
def __init__(self, i_parent, i_width, i_row, i_column, i_text):
test.set(i_text)
.
.
.
I have written a working solution. As I mentioned in my comment, the test variable should be an instance variable (self). I have added several comments to my example code for the better understanding.
Code:
import tkinter as tk
def temp():
print(entry_inst.get_text()) # Printing the result of "get_text" method of "entry_inst" object.
root = tk.Tk()
class makeEnetry:
def __init__(self, i_parent, i_width, i_row, i_column, i_text):
self.test = tk.StringVar()
self.test.set(i_text)
entry = tk.Entry(master=i_parent, width=i_width, textvariable=self.test)
entry.grid(row=i_row, column=i_column, padx=5, pady=5)
def get_text(self):
return self.test.get()
entry_inst = makeEnetry(root, 20, 1, 1, "TEST") # Creating an object from "makeEnetry" class
button = tk.Button(root, text="PUSH ME", command=temp) # Creating a button which will call the "temp" function
button.grid(row=2, column=1)
tk.mainloop()
GUI:
Console output:
FYI: I have changed the text in the entry box and clicked to button.
>>> python3 test.py
TEST
TEST1
TEST12
TEST123
Any variable that you want external functions to have access to need to be a instance variable.
For example, if you do self.test = StringVar(), and use self.test everywhere inside the class instead of just test, then any code that has a reference to the instance of the class can access the variable.
the_entry = makeEnetry(root, 20, 1, 1, "Hello, world!")
...
print(the_entry.test.get())
However, there's nothing wrong with creating a getter or setter. For example, StringVar has a getter (.get()) and setter (.set(...)). The advantage of creating getters and setters is that it separates the internal implementation from the external interface. With a getter or setter, you can hide the fact that you're using a StringVar, the caller doesn't need to know.
The thing with functions, instance variables, and with getters and setters, is that you are creating a user interface or API. You are creating an object and then telling the outside world "this is how you interact with this object". Sometimes getters and setters make sense, sometimes they don't. It depends on what you want the object UI/API to be, and whether or not you want to expose internal implementation details to the outside world.
In this specific case it seems like the_entry.get_text() is a cleaner interface than the_entry.test.get(...) since it gives you more freedom in changing the internal implementation without affecting code that uses this object. It all boils down to how you want external code to interact with the object you've created. Should the caller know that this object uses a StringVar, or should it just know that it can call get_text to interact with it?

Unable to access a variable in a function which belongs to other function of same class

I am creating a GUI with tkinter in python.I am trying to access a variable in a function which belongs to other function in same class.Getting Frame2 object has no attribute self.workingarea.The error comes from tools function.I am trying to access self.workingarea from projectwindow function in tools function.line no:28
class Frame2:
def __init__(self,root):
self.list=["label","Button","Entry","Text","Frame","RadioButton","Checkbutton","Canvas","LabelFrame","Notebook","ScaleWidget"]
self.w2=root
self.w2.state('zoomed')
self.w2.title("IDE")
self.w2.configure(background="white")
self.tools()
self.projectwindow()
#=============
def projectwindow(self):
self.workingarea=Tk()
self.workingarea.geometry('930x660+5+25')
self.workingarea.mainloop()
#================
def tools(self):
self.prop=ttk.Notebook(self.w2,width=self.w2.winfo_screenwidth()-int(self.w2.winfo_screenwidth()*0.7),height=self.w2.winfo_screenheight())
self.prop.place(x=self.w2.winfo_screenwidth()-int(self.w2.winfo_screenwidth()*0.3),y=0)
self.widgets=Frame(self.prop,bg="white")
self.root_properties=Frame(self.prop,bg="white")
self.properties=Frame(self.prop)
self.prop.add(self.widgets,text='Widgets',compound=TOP)
self.prop.add(self.root_properties,text='Root Window Properties',compound=TOP)
self.prop.add(self.properties,text='Properties',compound=TOP)
#=========
self.widget_section=LabelFrame(self.widgets,text='TK Widgets',padx=5,pady=15,bg='white')
self.widget_section.place(x=10,y=10)
self.obj=labels(self.workingarea,self.properties)
for self.i in range(11):
self.btn_widgets=Button(self.widget_section,text=self.list[self.i], borderwidth=2, relief="groove",width=33,font=("",14,""),command=self.obj.label)
self.btn_widgets.grid(row=self.i,column=0,pady=2)
The error is thrown as self.workingarea is not initialized.
Interchange calls to self.tools() and self.projectwindow() in the __init__ function.
TIP - Do not use 2 mainloop in the same thread. Rather use TopLevel widget

Tkinter - StringVar() trace not executing command

I wrote this code to be a version manager, but it doesn't execute the command changeDir(). Why?
https://pastebin.com/VSnhzRzF
You forgot to pass a 'name' argument to changeDir function. And there's no exception because your statement has no effect!
Snippet to represent the problem:
import sys
def exec_smth():
# execution without effect
exec('write_smth')
try:
# execution with exception because of missing argument
exec('write_smth()')
except TypeError as error:
# now we pass an argument
exec('write_smth("I failed because of %s" % error )')
def write_smth(smth):
sys.stdout.write(smth)
exec_smth()
Anyway, outside your __init__ function there're no StringVars at all thanks to garbage collector, so your code would fail anyway!
There're even more problems, because you never bind any of your sv{} to a widget and expect something in return! But ok, let's try to do things with exec:
try:
import tkinter as tk
except ImportError:
import Tkinter as tk
class App(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self.entries = []
for _ in range(5):
exec('self.sv{} = tk.StringVar()'.format(_))
exec('self.sv{}.trace("w", self.change_sv)'.format(_))
exec('self.entries.append(tk.Entry(self, text="", textvariable=self.sv{}))'.format(_))
for entry in self.entries:
entry.pack()
def change_sv(*args):
# get id of a variable (you can't rely on that (0-9)!)
idx = args[1][-1:]
# get new value
value = getattr(args[0], 'sv{}'.format(idx)).get()
# result
print('Value changed in self.sv%s to %s!' % (idx, value))
app = App()
app.mainloop()
Output:
As you see - we always need a reference to StringVars and I think that option with a list of them is far better!
Note: If you need to pass something to callback function - use a lambda function! All code tested with Python 3.
Links:
The Variable Classes
Tkinter Callbacks
Behavior of exec function in Python 2 and Python 3

Error message in bind key event

I am struggling to bind a left arrow press with a printed message. Any thoughts? I've searched this site and seem to be following the same instructions others have used, but it's still not working! I am very new to Python (and coding in general) and would really appreciate the help!
The error message:
NameError: name 'onArrowKey' is not defined
Relevant code:
from Tkinter import*
class FullScreenApp(object):
def __init__(self, master):
self.master=master
pad=3
self._geom='200x200+0+0'
master.geometry("{0}x{1}+0+0".format(
master.winfo_screenwidth()-pad, master.winfo_screenheight()-pad))
master.bind('<Escape>',self.toggle_geom)
def toggle_geom(self,event):
geom=self.master.winfo_geometry()
print(geom,self._geom)
self.master.geometry(self._geom)
self._geom=geom
def onArrowKey(self,event):
print 'Got arrow key press'
root=Tk()
root.bind('<Left>', onArrowKey)
root.config(background="black")
root.title("Who buzzed in first?")
app=FullScreenApp(root)
root.mainloop()
In the context you're writing in, onArrowKey has no definition. Move the def onArrowKey out of the FullScreenApp class, so that the context is right, or call app.onArrowKey instead of onArrowKey (after assigning app).
I guess you should move the problematic statement (root.bind('<Left>', onArrowKey)) in the __init__ of your class :
like this :
master.bind('<Left>', self.onArrowKey)

TkInter: How to call a variable from a callback function button?

I am a absolutly beginner in Tkinter and I need already help:
I wanted to open a file with a button. I found everywhere this very simple example:
from Tkinter import *
from tkFileDialog import askopenfilename
def callback():
name= askopenfilename()
print name
errmsg = 'Error!'
Button(text='File Open', command=callback).pack(fill=X)
mainloop()
But how can I call now the variable "name" from the function callback? I need this variable outside of this function! Of course, I can also open the file also in the callback function, but I need the opened file to save the content in an array and work with the array...
The best approach would be to make callback a method in a class:
class Asker(object):
def __init__(self):
self.name = None
def callback(self):
self.name = askopenfilename()
print self.name
ask = Asker()
Button(text='File Open', command=ask.callback).pack(fill=X)
Now, object ask persists, and ask.name is None if the callback has not executed yet, and after it has, the result of askopenfilename.
You could use a global instead but there's really no advantage in so doing so I recommend you use this class-based approach.
If you need some variable outside a function you need a global variable
name="" # if you don't call the function it'll remain empty!
def callback():
global name
name= askopenfilename()
print name

Categories

Resources