在python tkinter应用程序中引用一个全局对象

时间:2015-08-28 15:40:30

标签: python tkinter

当我选择另一个小部件时,我正在尝试更新python tkinter应用程序中的标签。

我创建了一个小工具,演示了这个问题。该工具将创建一个带有标签的小GUI。此标签应显示所选框的编号。

Image of tool

问题是当通过鼠标单击选择框号时,该数字不会显示在顶部标签中。单击框号应该调用setSelected,它应该调用app.setLabel(string)。但是,我收到错误“全局名称'app'未定义”

如何让对象'app'成为全局?

#!/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()

1 个答案:

答案 0 :(得分:1)

问题是您在root内部创建Tk()root.mainloop()应用)并致电__init__(),因此app无法完全创建,因为只有从__init__()返回时才会创建,但在关闭应用程序之前不会这样做。

对您的案例最简单的解决方案是移动root对象outisde Gui()类。示例 -

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()