Reputation: 205
I'm trying to update a label in a python tkinter application when another widget is selected.
I created a small tool, that demonstrates the issue. The tool will create a small GUI with a label on top. This label should show the number of the box that was selected.
Problem is that when a box number is selected by a mouse click, the number is not shown in the top label. Clicking the box number should call setSelected, which should call app.setLabel(string). However, I get the error "global name 'app' is not defined"
How do I make the object 'app' global?
#!/usr/bin/env python
import Tkinter
def setSelected(string):
app.setLabel(string)
class Gui():
Boxes = []
def __init__(self):
self._root = Tkinter.Tk()
self._root.protocol("WM_DELETE_WINDOW", self._applicationExit)
self._string = Tkinter.StringVar()
self.setLabel('None')
self._label = Tkinter.Label(self._root, textvariable = self._string,
width = 10)
self._label.grid(row = 0, column = 0, padx = 5, pady = 5)
self._createBoxOverview()
self._root.mainloop()
def _applicationExit(self, event = None):
self._root.destroy()
def _createBoxOverview(self):
_frame = Tkinter.LabelFrame(self._root, text = 'Boxes')
for _id in range(4):
self.Boxes.append(Box(_frame, _id))
self.Boxes[_id].grid(row = 0, column = _id)
_frame.grid(row = 1, column = 0, padx = 5, pady = 5)
def setLabel(self, string):
self._string.set(string)
class Box(Tkinter.Label):
def __init__(self, master, id):
Tkinter.Label.__init__(self, master)
self._id = str(id)
self._text = Tkinter.StringVar()
self._text.set(self._id)
self.config(textvariable = self._text, width = 3)
self.bind("<Button-1>", self._onSelect)
def _onSelect(self, event):
setSelected(self._id)
if __name__ == '__main__':
app = Gui()
Upvotes: 1
Views: 638
Reputation: 90889
The issue is that you are creating root
(Tk()
App) and calling root.mainloop()
, inside __init__()
itself, so app
does not completely get created, since it would only get created if you return from __init__()
, but you do not do that until you close the app.
The easiest solution for your case would be to move the root
object outisde Gui()
class. Example -
import Tkinter
def setSelected(string):
app.setLabel(string)
class Gui():
Boxes = []
def __init__(self, root):
self._root = root
self._root.protocol("WM_DELETE_WINDOW", self._applicationExit)
self._string = Tkinter.StringVar()
self.setLabel('None')
self._label = Tkinter.Label(self._root, textvariable = self._string,
width = 10)
self._label.grid(row = 0, column = 0, padx = 5, pady = 5)
self._createBoxOverview()
def _applicationExit(self, event = None):
self._root.destroy()
def _createBoxOverview(self):
_frame = Tkinter.LabelFrame(self._root, text = 'Boxes')
for _id in range(4):
self.Boxes.append(Box(_frame, _id))
self.Boxes[_id].grid(row = 0, column = _id)
_frame.grid(row = 1, column = 0, padx = 5, pady = 5)
def setLabel(self, string):
self._string.set(string)
class Box(Tkinter.Label):
def __init__(self, master, id):
Tkinter.Label.__init__(self, master)
self._id = str(id)
self._text = Tkinter.StringVar()
self._text.set(self._id)
self.config(textvariable = self._text, width = 3)
self.bind("<Button-1>", self._onSelect)
def _onSelect(self, event):
setSelected(self._id)
if __name__ == '__main__':
root = Tkinter.Tk()
app = Gui(root)
root.mainloop()
Upvotes: 1