我是 Stack Overflow 的新成员。
我找到了这个线程,但不允许对其发表评论或提问,所以我想我只是在这里引用它:How can I make a in interactive list in Python's Tkinter complete with buttons that can edit those listings?

from tkinter import *
import os
import easygui as eg

class App:

    def __init__(self, master):
        frame = Frame(master)
        frame.pack()

        # character box
        Label(frame, text = "Characters Editor").grid(row = 0, column = 0, rowspan = 1, columnspan = 2)
        charbox = Listbox(frame)
        for chars in []:
            charbox.insert(END, chars)
        charbox.grid(row = 1, column = 0, rowspan = 5)
        charadd = Button(frame, text = "   Add   ", command = self.addchar).grid(row = 1, column = 1)
        charremove = Button(frame, text = "Remove", command = self.removechar).grid(row = 2, column = 1)
        charedit = Button(frame, text = "    Edit    ", command = self.editchar).grid(row = 3, column = 1)

    def addchar(self):
        print("not implemented yet")
    def removechar(self):
        print("not implemented yet")
    def editchar(self):
        print("not implemented yet")


root = Tk()
root.wm_title("IA Development Kit")
app = App(root)
root.mainloop()

有人可以向我解释为什么最后一行是 root.mainloop() 吗?
作为 Python 的新手,并且来自面向过程但没有面向对象经验的背景,我会认为它应该是 app.mainloop()。

实际上 app = App(root) , app 在其余代码中再也没有使用过!我无法理解为什么 root.mainloop() 仍然有效。

最佳答案

我不确定您是否会发现这个答案令人满意,但是您调用 root.mainloop() 是因为 root 是具有 mainloop 方法的对象。在您提供的代码中, App 没有 mainloop 函数。

简单来说,这就是 tkinter 的工作方式——你总是通过调用根窗口的 mainloop 方法来结束你的脚本。当该方法返回时,您的程序将退出。

让我们从头开始。最简单的非 OO Tkinter 程序将类似于以下示例。请注意,这是一个 python 2.x 示例,我不使用全局导入,因为我认为全局导入不好。

import Tkinter as tk
root = tk.Tk()
<your widgets go here>
root.mainloop()

许多人发现纯过程风格不是编写代码的有效方式,因此他们可能会选择以面向对象的风格编写代码。将“应用程序”视为单例对象是很自然的。有很多方法可以做到这一点 - 不幸的是,您问题中的方法不是更清晰的方法之一。

IMO 稍微好一点的方法是像这样构造代码:
class App(tk.Tk):
    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)
        <your widgets go here>
app = App()
app.mainloop()

在这种情况下, mainloop 仍然被调用,尽管现在它是 App 的一个方法,因为 App 继承自 Tk 。它在概念上与 root.mainloop() 相同,因为在这种情况下,app 是根窗口,即使它具有不同的名称。

所以,在这两种情况下,mainloop 都是属于根窗口的方法。在这两种情况下,必须调用 GUI 才能正常运行。

还有第三种变体,这是您选择的代码正在使用的。通过这种变体,有几种方法可以实现它。变化是您的问题使用一个类来定义 GUI,但不从 Tk 继承。这完全没问题,但您仍然必须在某个时候调用 mainloop。由于您没有在类中创建(或继承) mainloop 函数,因此您必须调用与根窗口关联的函数。我所说的变化是将 App 实例添加到根窗口的方式和位置,以及最终调用 mainloop 的方式。

我个人更喜欢 App 继承自 Frame ,并且您将应用程序打包到应用程序的定义之外。我使用的模板如下所示:
class App(tk.Frame):
    def __init__(self, *args, **kwargs):
        tk.Frame.__init__(self, *args, **kwargs)
        <your widgets go here>

if __name__ == "__main__":
    root = tk.Tk()
    app = App(root)
    app.pack(fill="both", expand=True)
    root.mainloop()

在最后一个示例中,approot 是两个完全不同的对象。 app 表示存在于根窗口内的框架。框架通常以这种方式使用,作为其他小部件组的容器。

因此,在所有情况下,都必须调用 mainloop。它在哪里以及如何调用,在某种程度上取决于您的编码风格。有些人喜欢从根窗口继承,有些人不喜欢。无论哪种情况,您都必须调用根窗口的 mainloop 函数。

关于Python:Tkinter:为什么是 root.mainloop() 而不是 app.mainloop(),我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/22698980/

10-09 02:09