【发布时间】:2021-03-11 12:49:19
【问题描述】:
好的,所以我几乎要为这个而失去理智了。
我正在开发一个小型应用程序,它从输入 XML 文件中获取问题,将它们显示在屏幕上,获取答案并将其写回到输出 XML 中,使用 tkinter 进行 GUI 和 ElementTree 进行 XML 处理。 每个问题可能有多个检查和子问题,它们会根据需要动态显示在各自的框架上。
主窗口由main 创建为MainWindow 类实例(其中包含所有tkinter 的东西和一堆有用的方法),在代码的最后:
def main():
global app
window = Tk()
app = MainWindow(window)
window.mainloop()
if __name__ == '__main__':
main()
这应该使 'app' 成为一个可以从代码中的任何位置访问的全局变量,对吧?
.....显然不是?
我创建了 Question 类,它存储从 XML 中提取的属性,处理文本的显示,并为 XML 中的每个元素创建一个 Check 类,并为 XML 中的每个元素创建一个 Subquestion 类。
Question类如下:
class Question:
def __init__(self, element):
self.element = element
self.question_text = element.get('text')
self.ok = element.get('ok')
self.answer = element.get('r')
self.comment = element.get('comment')
if element.find('check') is None:
#print(app)
pass
else:
#print(app)
for check in element.iter('check'):
Check(check)
for subq in element.iter('subquest'):
SubQuestion(subq)
还有 Check 类,它处理复选框的创建以及将它们各自的答案写入 ElementTree:
class Check:
def __init__(self, element):
self.element = element
self.check_text = element.get('text')
self.answer = element.get('r')
self.var = IntVar()
self.create_check()
def create_check(self):
print('check created')
print(app)
Checkbutton(app.frameChk, text=self.check_text, variable=self.var, command=self.write_check).pack(side=LEFT)
def write_check(self):
self.element.set('r', self.var.get())
print('check written')
到目前为止,一切都很好。它按预期工作,出现复选框并提交它们的值,没有问题
但是...您是否注意到 Check 类中的 create_check 方法在创建复选框时引用了 app.frameChk?这是为复选框保留的 Tk 框架,由 MainWindow 的 __init__ 方法创建。这个create_check 方法可以毫无问题地访问app,即使其中没有global 关键字。我什至添加了print(app) 只是为了确保。
果然,每次创建复选框时,它都会将<__main__.MainWindow object at 0x0000024CCC557BE0>" 打印到控制台。
但是...在问题的__init__ 方法(或其他任何地方,就此而言),我似乎无法访问与app 相关的任何内容,它抛出classes_app.py", line 129, in __init__ - print(app) NameError: name 'app' is not defined
到底为什么?这两个类不从其他类继承任何内容,并且在层次上“相等”,只是程序中的两个平均类(实际上,Question 是创建 Check 实例的类!)。一个人认识全球而其他人不认识?
最令人难以置信的是:Check 类中没有 global 关键字,它仍然有效吗?
到目前为止我已经尝试过:
1 - 在全局范围内的 main 函数之外声明 app = MainWindow(window)。什么都没有。
2 - 在程序的每个函数中使用global 关键字,看看他们是否得到它。没有。
3 - 将main 函数放在代码的最顶部,这样将是第一个
app 的声明似乎也没什么用。
4 - 上述解决方案和试错法的任意组合。
5 - 为 python 全局代码女神牺牲一块主板。
请注意,我对 python 还很陌生,所以我可能对全局变量的理解非常错误,或者完全不理解,但从文档所说,使用 global 关键字声明的变量应该是全局变量,并且全局变量可以从代码中的任何和所有函数和方法中访问,对吧?
如果你问我为什么这么需要 app = MainWindow(window) 是全局的:会有一个全局函数来清理每个问题之间的小部件:
def destroy_widgets(parent):
for widget in parent.winfo_children():
widget.destroy()
例如,在类的方法中,我将其称为destroy_widgets(app.frameChk)。这就是我第一次遇到这个问题的方式。
我会发布整个代码,但它包含所有这些 tkinter 定义。如果你们认为有必要,我当然会。
任何帮助或见解将不胜感激,在此先感谢,这个社区是黄金!
【问题讨论】:
标签: python tkinter global-variables global elementtree