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

mutliple entry widgets and one button widget in tkinter

我正在尝试制作两个输入框和一个处理这两个条目的 'OK' 按钮: 我不明白 init() 函数或必须包含 'self' 的原因。 我想访问此 class 和 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)

您的方法存在根本性缺陷。 mainloop() 按照它说的去做:开始一个循环。在循环结束之前,它后面的行不会执行 - 也就是说,直到您的应用程序关闭。因为你已经有了一个 class 里面有 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 应用程序之前,更深入地了解对象和 classes 等基本概念的工作原理。

这是一个快速解决方法。

你的版本和TigerhawkT3的修改版本的问题是,当你关闭window时,Entry小部件不再有效,所以你需要在关闭[=之前保存数据52=]。一种方法是将 Tkinter StringVars 附加到 Entry 小部件。 StringVar 中的值将在 window 关闭后可用。

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__()函数是myDoseclass的一个方法。 class 的 __init__() 方法在创建 class 的实例时被调用。在您执行

时发生的代码中
D = myDose()

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

D = myDose(tk.Tk())

首先创建 Tkinter 根 window,然后传递给 myDose;该根 window 然后可用于我的 __init__() 作为其 root 参数。

名称self 用于class 中以引用当前class 实例。在 class 之外,我们需要使用我们为实例分配的实际名称,在本例中为 D.

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

如果这就是您想要的 - 销毁 window 并访问小部件中的值 - 您需要在销毁 window.[=16 之前保存这些值=]

例如,在您的提交中,您可以像这样保存值:

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

一旦 window 被销毁,您仍然拥有对应用程序对象的引用,因此您仍然可以访问 class 的非小部件属性:

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

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

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

您可以随心所欲地编写程序,但我认为如果您坚持正常的设计模式,那么长期 运行 您的代码将更易于维护和修改。将您的 "real" 代码移动到应用 class 的方法中,这将消除与被销毁的小部件相关的所有问题。