我是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()仍然有效。
答案 0 :(得分:4)
我不确定您是否会发现此答案令人满意,但您致电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()
许多人发现纯粹的程序风格不是编写代码的有效方式,因此他们可能会选择以面向对象的方式编写代码。很自然地想到了应用程序&#34;作为单身对象。有很多方法可以做到这一点 - 遗憾的是,问题中的一个方法并不是更明确的方法之一。
稍微好一点的方法,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()
在最后一个示例中,app
和root
是两个完全不同的对象。 app
代表在根窗口中的框架。帧通常以这种方式使用,作为其他小部件组的容器。
因此,在所有情况下,都必须调用mainloop
。 在哪里被调用,以及如何,取决于你的编码风格。有些人喜欢从根窗口继承,有些人不喜欢。在任何一种情况下,您都必须调用根窗口的mainloop
函数。
答案 1 :(得分:1)
我测试了两个,就像你看到的那样:
一个用“app”编写。 +“。pack()”,一个调用“大型机”。 +“。grid()”
#-*- 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()
这个实例适用于python 2.7。在那个测试甚至应用程序。可以处理“mainloop()” 该脚本打开2个窗口,一个接一个(如果你关闭第一个)并且第一个程序被格式化,没有尝试在pack()clamps中写colum = 3 ... stuff。
我仍然开始使用Tkinter所以不要打我,只是尝试..希望我能帮助回答你的问题。 一切顺利,Ingo
答案 2 :(得分:0)
App
对象只是您的应用代码,您调用App(root)
的原因是为您的类创建一个实例,然后该类可以访问您的根窗口。
它在__init__
方法中接收此引用:
def __init__(self, master):
# master refers to the root window now
...
你可以看到App
对象的整个定义(由以class App:
开头的块给出),它甚至没有mainloop
方法,所以要启动主Tkinter循环,你必须在根窗口调用它。
在example in the Python2 documentation中,他们执行调用它,因为您怀疑应该这样做,但请注意他们的示例类是Tk对象Frame
的子类。在您的示例代码中,App
是一个旧式类,不会继承任何内容。