首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么是root.mainloop()而不是app.mainloop()

为什么是root.mainloop()而不是app.mainloop()
EN

Stack Overflow用户
提问于 2014-03-28 04:54:25
回答 3查看 29.4K关注 0票数 4

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

代码语言:javascript
复制
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()仍然有效。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2014-03-28 05:11:51

我不确定您是否会对这个答案感到满意,但是您可以调用root.mainloop(),因为root是具有mainloop方法的对象。在您给出的代码中,App没有mainloop函数。

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

让我们从头开始。最简单的、非面向对象的Tkinter程序将如下例所示。请注意,这是一个python2.x示例,我没有使用全局导入,因为我认为全局导入是不好的。

代码语言:javascript
复制
import Tkinter as tk
root = tk.Tk()
<your widgets go here>
root.mainloop()

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

一种稍微好一点的方法,IMO,是这样构造代码:

代码语言:javascript
复制
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正常工作。

还有第三个变体,就是您选择的代码正在使用的代码。对于这个变体,有几种方法可以实现它。不同的是,您的问题使用一个类来定义图形用户界面,但不是从Tk继承的。这是非常好的,但是您仍然必须在某些时候调用mainloop。由于您没有在类中创建(或继承) mainloop函数,因此必须调用与根窗口关联的函数。我提到的变化是如何以及在何处将App实例添加到根窗口,以及mainloop最终是如何调用的。

就我个人而言,我更喜欢App继承自Frame,并将应用程序打包到应用程序定义之外。我使用的模板如下所示:

代码语言:javascript
复制
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函数。

票数 8
EN

Stack Overflow用户

发布于 2017-07-29 18:54:41

我测试了这两个,就像你看到的:

一种是用"app.“+ ".pack()"编写的,另一种是用"mainframe.”+ ".grid()"编写的。

代码语言:javascript
复制
 #-*- coding: utf-8 -*-
#THIS IS THE "MAINFRAME." - PART
from Tkinter import *
import ttk

def show():
    p = password.get() #get password from entry
    print(p)


root = Tk()
root.title("Ingos first program")

mainframe = ttk.Frame(root, padding="30 30 60 12")
mainframe.grid(column=0, row=0, sticky=(N, W, E, S))
mainframe.columnconfigure(0, weight=1)
mainframe.rowconfigure(0, weight=1)


password = StringVar() #Password variable
passEntry = Entry(mainframe, textvariable=password, show='*').grid(column=3, row=3, sticky=S)
submit = Button(mainframe, text='Show Console',command=show).grid(column=3, row=4, sticky=S)

root.mainloop()
def show():
    p = password.get() #get password from entry
    print(p)

#THIS IS THE "APP."-PART. BOTH WORKS FINE.
app = Tk()
app.title("Ingos first program")
password = StringVar() #Password variable
passEntry = Entry(app, textvariable=password, show='#').pack()
submit = Button(app, text='Show Console',command=show).pack()

app.mainloop()

这个实例在python2.7上运行得很好。在测试中,甚至连应用程序也是如此。可以处理"mainloop()“的那段脚本打开两个窗口,一个接一个(如果你关闭第一个)并且第一个程序是格式化的,没有尝试写colum=3...pack()夹子里的东西。

我还是开始了Tkinter,所以别和我争,只是试着..希望我能帮助你回答你的问题。万事如意,英戈

票数 1
EN

Stack Overflow用户

发布于 2014-03-28 05:03:15

App对象只是您的应用程序代码,您调用App(root)的原因是使用您的类创建一个实例,然后该类可以访问您的根窗口。

它在__init__方法中接收此引用:

代码语言:javascript
复制
def __init__(self, master):
    # master refers to the root window now
    ...

您可以看到App对象的完整定义(由以class App:开头的代码块给出),而且它甚至没有mainloop方法,因此要启动主Tkinter循环,您必须在根窗口上调用它。

example in the Python2 documentation中,它们确实会像您怀疑的那样调用它,但请注意,它们的示例类是Tk object Frame的子类。在您的示例代码中,App是一个不继承任何内容的老式类。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/22698980

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档