多个条目小部件和tkinter中的一个按钮小部件

时间:2016-05-27 20:45:52

标签: python class tkinter init self

我正在尝试制作两个输入框和一个' OK'处理两个条目的按钮:     我不理解 init ()函数或原因' self'必须包括这样做。 我想访问这个类和mainloop之外的条目。条目应该是字符串类型。

from tkinter import *
root = Tk()
root.geometry("550x145+500+300")

class myDose:
    def __init__(self):

        l1 = Label(text="Enter the prescription dose to three (3) decimal places [cGy]").pack()
        e1 = Entry(root)
        e1.pack()

        l2 = Label(text="Save new excel file as...").pack()
        e2 = Entry(root)
        e2.pack()

        l3 = Label(text="click 'OK', and then close window.").pack()

        b = Button(root, text="OK", command=submit)
        b.pack()

    def submit(self):
        print(e1.get())
        print(e2.get())

D = myDose()
root.mainloop()

#I want to access the entries, e1 and e2, outside the mainloop
print(D.e1)
print(D.e2)

3 个答案:

答案 0 :(得分:1)

问题是mainloop在根窗口被销毁之前不会退出。一旦根窗口被销毁,您就无法再访问根窗口内的小部件。但是,您可以访问该对象的非窗口小部件属性。

如果这是您想要的 - 破坏窗口并访问窗口小部件中的值 - 您需要在销毁窗口之前保存这些值。

例如,在您的提交中,您可以保存以下值:

def submit(self):
    self.data = {"e1": self.e1.get(), "e2": self.e2.get()}

一旦窗口被销毁,您仍然可以引用应用程序对象,因此您仍然可以访问该类的非窗口小部件属性:

...
D = myDose(root)
root.mainloop()

print D.data["e1"]
print D.data["e2"]

根据对原始问题的评论,您提到稍后在您的代码中,您需要使用askopenfilename。如果是这种情况,您应该重新考虑在mainloop之后运行代码的必要性。 Tkinter设计为只创建一次根窗口,并且程序在mainloop退出后立即退出。

您可以随意编写程序,但我认为如果您坚持正常的设计模式,您的代码将更容易维护和修改。移动你的真实"将代码编写到app类的方法中,这将消除与小部件被销毁相关的所有问题。

答案 1 :(得分:0)

您的方法存在根本缺陷。 mainloop()做了它所说的:开始一个循环。在该循环结束之前,不会执行其后面的行 - 这意味着,直到您的应用程序关闭。既然你已经有了一个带有Tkinter东西的类,那么就完成向OO方法的转变:

from tkinter import *

class myDose:
    def __init__(self, root):
        root.geometry("550x145+500+300")

        self.l1 = Label(root, text="Enter the prescription dose to three (3) decimal places [cGy]")
        self.l1.pack()
        self.e1 = Entry(root)
        self.e1.pack()

        self.l2 = Label(root, text="Save new excel file as...")
        self.l2.pack()
        self.e2 = Entry(root)
        self.e2.pack()

        self.l3 = Label(root, text="click 'OK', and then close window.")
        self.l3.pack()

        self.b = Button(root, text="OK", command=self.submit)
        self.b.pack()

    def submit(self):
        print(self.e1.get())
        print(self.e2.get())

root = Tk()
D = myDose(root)
root.mainloop()

我建议在创建完整的GUI应用程序之前,更全面地了解对象和类等基本概念的工作原理。

答案 2 :(得分:0)

这是一个快速解决方案。

您的版本和TigerhawkT3修改版本的问题在于,当您关闭窗口时,Entry窗口小部件不再有效,因此您需要在关闭窗口之前保存数据。一种方法是将Tkinter StringVar附加到Entry小部件。窗口关闭后,StringVar s中的值将可用。

import tkinter as tk

class myDose:
    def __init__(self, root):
        root.geometry("550x145+500+300")

        l = tk.Label(root, text="Enter the prescription dose to three (3) decimal places [cGy]")
        l.pack()
        self.dosage = tk.StringVar()
        e = tk.Entry(root, textvariable=self.dosage)
        e.pack()

        l = tk.Label(root, text="Save new excel file as...")
        l.pack()
        self.savename = tk.StringVar() 
        e = tk.Entry(root, textvariable=self.savename)
        e.pack()

        l = tk.Label(root, text="Enter the data and then close window.")
        l.pack()

        root.mainloop()

D = myDose(tk.Tk())

print(D.dosage.get())
print(D.savename.get())

请注意,我已更改import声明。它

更清洁
from tkinter import *

因为你的命名空间超过100个名称,导致潜在的名称冲突。

__init__()函数是myDose类的方法。创建该类的实例时,将调用类的__init__()方法。在您执行的代码中

D = myDose()

在我的版本中执行此行的时间:

D = myDose(tk.Tk())

首先创建Tkinter根窗口,然后传递给myDose;然后,根窗口可以作为__init__()参数用于我的root

在类中使用名称self来引用当前的类实例。在课外,我们需要使用我们为实例分配的实际名称,在本例中为D