pydata

Keep Looking, Don't Settle

Introduction to Tkinter 01: frame and page

tkinter的简单介绍

  1. 首先建立一个frame,类似于框架

  2. 然后把各个page pack到frame上面,也就是下面code的show_frame test

  3. 显示不同的东西通过页面之间的跳转来实现,从startPage到pageOne,再从pageOne回到startPage test

import Tkinter as tk

'''
self: self表示当前的对象。

parent: 表示当前对象的父对象。除了root,tkinter的所有widgets都有一个父widget。

controller: 用来连接几个不同的page(frame)的公共数据。这样的话,每一个page可以
独立的update数据,而不需要调用其他page。如果它需要作用于另一个page(比如通过click
一个buttom,使得另一个页面变成top页面从而可视,这时候就可以用controller来让它可视。


container上面有不同的frame(page).它们被保存在frames里面,而frames属于myFrame,
所以show_frame没有办法像prt一样从myFrame里面拿出来。

startPage其实是继承了container,而不仅仅是tk.Frame. 但是它又要调用show_frame,
所以它的__init__需要两个参数,第一个是parent,第二个其实是连接myFrame的self,用来
调用show_frame。所以会出现 frame = startPage(container, self),因为这个,
controller.show_frame(startPage) 就变成了self.show_frame(startPage),
这样show_frame才会被调用,startPage才会被显示

prt函数只是在startPage打印,而且它不需要使用myFrame的任何属性,所以它可以单独放外面,
我们也可以把它放到myFrame下面,就像myFrame2里面那样。那样的话就成了myFrame2的属性,
所以在startPage里面就要使用controller.prt()

'''


class myFrame1(tk.Tk):
    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 F in (startPage, pageOne):
            frame = F(container, self)  #startPage继承了container
            frame.grid(row=0, column=0, sticky="nsew")
            self.frames[F] = frame

        self.show_frame(startPage)

    def show_frame(self, page_name):
        frame = self.frames[page_name]
        frame.tkraise()


def prt():
    print "this is test"

class startPage(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        self.controller = controller

        label = tk.Label(self, text = "Start Page")
        label.pack(pady = 10, padx = 10)

        # 在__init__下面,可以写self.controller或者controller,它们是一样的
        # 但是在上面的show_frame(不在__init__下),那么就需要self.frames,要不然找不到frames
        b1 = tk.Button(self, text = "Page One", command = lambda: self.controller.show_frame(pageOne))
        b1.pack()

        b2 = tk.Button(self, text = "Print", command = lambda: prt())
        b2.pack()

class pageOne(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        self.controller = controller

        label = tk.Label(self, text = "Page one")
        label.pack(pady = 10, padx = 10)

        b1 = tk.Button(self, text = "go home", command = lambda: self.controller.show_frame(startPage))
        b1.pack()


app1 = myFrame1()
app1.mainloop()


##########  This is to show how to put prt inside myFrame, compared with above ###########


import Tkinter as tk

class myFrame2(tk.Tk):
    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 = {}
        frame = startPage(container, self)  #
        frame.grid(row=0, column=0, sticky="nsew")
        self.frames[startPage] = frame

        self.show_frame(startPage)

    def show_frame(self, cont):
        frame = self.frames[cont]
        frame.tkraise()

    def prt(self):
        print "this is test"

class startPage(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)

        label = tk.Label(self, text = "Page one")
        label.pack(pady = 10, padx = 10)

        b1 = tk.Button(self, text = "go home", command = lambda: controller.show_frame(startPage))
        b1.pack()

        b2 = tk.Button(self, text = "Print", command = lambda: controller.prt())
        b2.pack()

app2 = myFrame2()
app2.mainloop()



# ref:
# http://stackoverflow.com/questions/7300072/inheriting-from-frame-or-not-in-a-tkinter-application
# http://effbot.org/tkinterbook/tkinter-hello-again.htm
# http://stackoverflow.com/questions/17466561/best-way-to-structure-a-tkinter-application
# http://t1174779123.iteye.com/blog/2051485
# http://stackoverflow.com/questions/7546050/switch-between-two-frames-in-tkinter
# http://stackoverflow.com/questions/34301300/tkinter-understanding-how-to-switch-frames