下面是我典型的python tkinter程序的总体结构。

def funA():
    def funA1():
        def funA12():
            # stuff

    def funA2():
        # stuff

def funB():
    def funB1():
        # stuff

    def funB2():
        # stuff

def funC():
    def funC1():
        # stuff

    def funC2():
        # stuff


root = tk.Tk()

button1 = tk.Button(root, command=funA)
button1.pack()
button2 = tk.Button(root, command=funB)
button2.pack()
button3 = tk.Button(root, command=funC)
button3.pack()

当用户点击按钮1,2,3时,funA funB和funC将会弹出另一个带有小部件的topllevel窗口。

我想知道这是否是编写python tkinter程序的正确方式?当然,即使我这样写也可以,但这是最好的方式吗?这听起来很愚蠢,但当我看到其他人写的代码时,他们的代码并没有被一堆函数搞得乱七八糟,而且他们主要是有类。

有没有什么具体的结构是我们应该遵循的?在开始编写python程序之前,我应该如何计划?

我知道在编程中没有所谓的最佳实践,我也没有要求它。我只是想要一些建议和解释,让我在自己学习Python时保持正确的方向。


当前回答

我更喜欢布莱恩·奥克利的回答。 这是一个例子,由Sentdex在Youtube上制作,去看看他的“gui with Tkinter”播放列表。

我认为把它放在这里很有意义因为它是OP的一个很好的例子,所以它也回答了这个由35个人提出的答案,但没有人回答;

@Bryan Oakley你知道任何好的样本代码在互联网上,我可以 研究它们的结构?- Chris Aung Jul 5 '13在8:35

import tkinter as tk

LARGE_FONT= ("Verdana", 12)

class SeaofBTCapp(tk.Tk):
    """
    tkinter example app with OOP
    """

    def __init__(self, *args, **kwargs):
        
        tk.Tk.__init__(self, *args, **kwargs)
        container = tk.Frame(self)

        container.pack(side="top", fill="both", expand = True)

        container.grid_rowconfigure(0, weight=1)
        container.grid_columnconfigure(0, weight=1)

        self.frames = {}

        for frame_class in (StartPage,PageOne, PageTwo):

            frame = frame_class(container, self)

            self.frames[frame_class] = frame

            frame.grid(row=0, column=0, sticky="nsew")
    

        self.show_frame(StartPage)

    def show_frame(self, cont):
        """
        Put specific frame on top
        """

        frame = self.frames[cont]
        frame.tkraise()

        
class StartPage(tk.Frame):
    """
    Starting frame for app
    """

    def __init__(self, parent, controller):
        tk.Frame.__init__(self,parent,bg='grey')
        label = tk.Label(self, text="Start Page", font=LARGE_FONT)
        label.pack(pady=10,padx=10)

        button_page1 = tk.Button(self, text = 'Visit Page 1', command= lambda: controller.show_frame(PageOne))
        button_page1.pack()

        button_page2 = tk.Button(self, text = 'Visit Page 2', command= lambda: controller.show_frame(PageTwo))
        button_page2.pack()

class PageOne(tk.Frame):
    """
    First page of program
    """

    def __init__(self,parent,controller):
        tk.Frame.__init__(self,parent,bg='light blue')
        label = tk.Label(self, text="Page one", font=LARGE_FONT)
        label.pack(pady=10,padx=10)

        button_home = tk.Button(self, text = 'Back to Home', command= lambda: controller.show_frame(StartPage))
        button_home.pack()

        button_home = tk.Button(self, text = 'Go to page2', command= lambda: controller.show_frame(PageTwo))
        button_home.pack()

class PageTwo(tk.Frame):
    """
    First page of program
    """

    def __init__(self,parent,controller):
        tk.Frame.__init__(self,parent,bg='light green')
        label = tk.Label(self, text="Page two", font=LARGE_FONT)
        label.pack(pady=10,padx=10)

        button_home = tk.Button(self, text = 'Back to Home', command= lambda: controller.show_frame(StartPage))
        button_home.pack()

        button_home = tk.Button(self, text = 'Go to page1', command= lambda: controller.show_frame(PageOne))
        button_home.pack()




app = SeaofBTCapp()
app.mainloop()

在这里也可以找到代码:[https://pythonprogramming.net/change-show-new-frame-tkinter/]

其他回答

我更喜欢布莱恩·奥克利的回答。 这是一个例子,由Sentdex在Youtube上制作,去看看他的“gui with Tkinter”播放列表。

我认为把它放在这里很有意义因为它是OP的一个很好的例子,所以它也回答了这个由35个人提出的答案,但没有人回答;

@Bryan Oakley你知道任何好的样本代码在互联网上,我可以 研究它们的结构?- Chris Aung Jul 5 '13在8:35

import tkinter as tk

LARGE_FONT= ("Verdana", 12)

class SeaofBTCapp(tk.Tk):
    """
    tkinter example app with OOP
    """

    def __init__(self, *args, **kwargs):
        
        tk.Tk.__init__(self, *args, **kwargs)
        container = tk.Frame(self)

        container.pack(side="top", fill="both", expand = True)

        container.grid_rowconfigure(0, weight=1)
        container.grid_columnconfigure(0, weight=1)

        self.frames = {}

        for frame_class in (StartPage,PageOne, PageTwo):

            frame = frame_class(container, self)

            self.frames[frame_class] = frame

            frame.grid(row=0, column=0, sticky="nsew")
    

        self.show_frame(StartPage)

    def show_frame(self, cont):
        """
        Put specific frame on top
        """

        frame = self.frames[cont]
        frame.tkraise()

        
class StartPage(tk.Frame):
    """
    Starting frame for app
    """

    def __init__(self, parent, controller):
        tk.Frame.__init__(self,parent,bg='grey')
        label = tk.Label(self, text="Start Page", font=LARGE_FONT)
        label.pack(pady=10,padx=10)

        button_page1 = tk.Button(self, text = 'Visit Page 1', command= lambda: controller.show_frame(PageOne))
        button_page1.pack()

        button_page2 = tk.Button(self, text = 'Visit Page 2', command= lambda: controller.show_frame(PageTwo))
        button_page2.pack()

class PageOne(tk.Frame):
    """
    First page of program
    """

    def __init__(self,parent,controller):
        tk.Frame.__init__(self,parent,bg='light blue')
        label = tk.Label(self, text="Page one", font=LARGE_FONT)
        label.pack(pady=10,padx=10)

        button_home = tk.Button(self, text = 'Back to Home', command= lambda: controller.show_frame(StartPage))
        button_home.pack()

        button_home = tk.Button(self, text = 'Go to page2', command= lambda: controller.show_frame(PageTwo))
        button_home.pack()

class PageTwo(tk.Frame):
    """
    First page of program
    """

    def __init__(self,parent,controller):
        tk.Frame.__init__(self,parent,bg='light green')
        label = tk.Label(self, text="Page two", font=LARGE_FONT)
        label.pack(pady=10,padx=10)

        button_home = tk.Button(self, text = 'Back to Home', command= lambda: controller.show_frame(StartPage))
        button_home.pack()

        button_home = tk.Button(self, text = 'Go to page1', command= lambda: controller.show_frame(PageOne))
        button_home.pack()




app = SeaofBTCapp()
app.mainloop()

在这里也可以找到代码:[https://pythonprogramming.net/change-show-new-frame-tkinter/]

使用类组织应用程序可以使您和其他与您一起工作的人轻松调试问题和改进应用程序。

你可以像这样轻松地组织你的应用程序:

class hello(Tk):
    def __init__(self):
        super(hello, self).__init__()
        self.btn = Button(text = "Click me", command=close)
        self.btn.pack()
    def close():
        self.destroy()

app = hello()
app.mainloop()

将每个顶级窗口放到它自己的单独类中,可以重用代码和更好的代码组织。窗口中出现的任何按钮和相关方法都应该在这个类中定义。下面是一个例子:

import tkinter as tk

class Demo1:
    def __init__(self, master):
        self.master = master
        self.frame = tk.Frame(self.master)
        self.button1 = tk.Button(self.frame, text = 'New Window', width = 25, command = self.new_window)
        self.button1.pack()
        self.frame.pack()
    def new_window(self):
        self.newWindow = tk.Toplevel(self.master)
        self.app = Demo2(self.newWindow)

class Demo2:
    def __init__(self, master):
        self.master = master
        self.frame = tk.Frame(self.master)
        self.quitButton = tk.Button(self.frame, text = 'Quit', width = 25, command = self.close_windows)
        self.quitButton.pack()
        self.frame.pack()
    def close_windows(self):
        self.master.destroy()

def main(): 
    root = tk.Tk()
    app = Demo1(root)
    root.mainloop()

if __name__ == '__main__':
    main()

还看到:

简单的hello world从tkinter文档 Tkinter示例代码的多个窗口,为什么不会正确加载按钮? Tkinter:如何显示/隐藏窗口

希望这能有所帮助。

OOP应该是方法,框架应该是类变量而不是实例变量。

from Tkinter import *
class App:
  def __init__(self, master):
    frame = Frame(master)
    frame.pack()
    self.button = Button(frame, 
                         text="QUIT", fg="red",
                         command=frame.quit)
    self.button.pack(side=LEFT)
    self.slogan = Button(frame,
                         text="Hello",
                         command=self.write_slogan)
    self.slogan.pack(side=LEFT)
  def write_slogan(self):
    print "Tkinter is easy to use!"

root = Tk()
app = App(root)
root.mainloop()

参考:http://www.python-course.eu/tkinter_buttons.php

这是个不错的结构;它会工作得很好。然而,当有人点击按钮或其他东西时,你必须在函数中有函数来执行命令

你能做的就是为这些写类然后在类中有方法来处理按钮点击之类的命令。

这里有一个例子:

import tkinter as tk

class Window1:
    def __init__(self, master):
        pass
        # Create labels, entries,buttons
    def button_click(self):
        pass
        # If button is clicked, run this method and open window 2


class Window2:
    def __init__(self, master):
        #create buttons,entries,etc

    def button_method(self):
        #run this when button click to close window
        self.master.destroy()

def main(): #run mianloop 
    root = tk.Tk()
    app = Window1(root)
    root.mainloop()

if __name__ == '__main__':
    main()

通常具有多个窗口的tk程序是多个大类,在__init__中创建所有的条目,标签等,然后每个方法都是用来处理按钮单击事件

没有正确的方法,只要是对你有用的,只要是可读的,你可以很容易地解释它,因为如果你不能很容易地解释你的程序,可能有更好的方法。

看看《思考Tkinter》。