在没有全局变量的情况下操作动态生成的tk-inter小部件

时间:2019-12-08 16:42:36

标签: python user-interface tkinter

此最小示例代码是有效的:

from tkinter import *

textbox =str()

def openpopup():

    popupwindow = Toplevel(root)
    global textbox
    textbox = Text(popupwindow, height=20, width=40,font="Courier")
    textbox.pack()

    textbox.delete(1.0, END)
    textbox.insert(1.0,"start")

    Button(popupwindow, text="do it", command=changepopup).pack()

def changepopup():
    global textbox
    textbox.delete(1.0, END)
    textbox.insert(1.0,"changed text")


root = Tk()
Button(root, text="open", command=openpopup).pack()
mainloop()

我的目标是在用户输入上动态打开一个弹出窗口,然后使各种gui元素进行交互。 我设法使用全局来做到这一点。我读过应该避免使用全局变量。

推荐的解决方法是什么?我可以避免使用全局变量吗?我知道这是范围界定的问题,这就是我提出此“解决方案”的方式。我对OOP不太熟悉,但是我有一种直觉,这可能是解决问题的方法。

3 个答案:

答案 0 :(得分:1)

面向对象的方式将是创建一个表示“弹出”对象的class。该类的初始化器方法__init__()可以创建弹出窗口的小部件,并充当Text小部件内容的存储区域。这样避免了使用全局变量,因为类的方法都具有第一个参数,通常调用self是类的is实例。

任何需要的数据都可以存储为self的属性,并且可以轻松地“共享”该类的所有方法。

避免全局变量的另一种主要方法是将它们作为参数显式传递给其他可调用对象,如main()在下面的示例代码中所做的那样。

这是一个基于您问题代码的示例:

from tkinter import *


class Popup:
    def __init__(self, parent):
        popup_window = Toplevel(parent)
        self.textbox = Text(popup_window, height=20, width=40, font="Courier")
        self.textbox.pack()
        self.textbox.insert(1.0, "start")

        btn_frame = Frame(popup_window)
        Button(btn_frame, text="Do it", command=self.do_it).pack(side=LEFT)
        Button(btn_frame, text="Close", command=popup_window.destroy).pack(side=LEFT)
        btn_frame.pack()

    def do_it(self):
        self.clear()
        self.textbox.insert(1.0, "changed text")

    def clear(self):
        self.textbox.delete(1.0, END)


def main():
    root = Tk()
    Button(root, text="Open", command=lambda: Popup(root)).pack()
    root.mainloop()

if __name__ == '__main__':
    main()

答案 1 :(得分:1)

  

问题:我可以避免使用全局变量吗?

是的,请考虑使用此OOP解决方案,而无需任何 global


参考:
-9.5. Inheritance
-class-and-instance-variables
-Dialog Windows


import tkinter as tk
from tkinter import tkSimpleDialog

class Popup(tkSimpleDialog.Dialog):
    # def buttonbox(self):
        # override if you don't want the standard buttons

    def body(self, master):
        self.text_content = ''
        self.text = tk.Text(self)
        self.text.pack()
        return self.text # initial focus

    def apply(self):
        self.text_content = self.text.get(1.0, tk.END)

class App(tk.Tk):
    def __init__(self):
        super().__init__()

        btn = tk.Button(self, text='Popup', command=self.on_popup)
        btn.pack()    

    def on_popup(self):
        # The widget `Popup(Dialog)`, waits to be destroyed.
        popup = Popup(self, title='MyPopup')
        print(popup.text_content)

if __name__ == '__main__':
    App().mainloop()

答案 2 :(得分:0)

您创建的全局变量textbox是不必要的。您只需将其从程序中删除即可。仍然会得到相同的行为

# textbox = str()

我希望我的回答会有所帮助。