tkinter - 使用按钮在帧之间来回切换

Posted

技术标签:

【中文标题】tkinter - 使用按钮在帧之间来回切换【英文标题】:tkinter - Going Back and Forth Between Frames Using Buttons 【发布时间】:2016-06-07 14:01:44 【问题描述】:

我需要功能,最好是一个功能,当按下下一个和后退按钮时,它可以在页面之间来回切换。我想这可以通过将布尔变量分配给后退和下一个按钮来完成(不确定是否可以这样做)以确定您是前进还是后退所有页面的有序列表。需要知道当前升起的框架的索引。索引可用于找出下一页,然后将其提升。如果当前索引为 0 或最后一个索引(在本例中为 2)并且您分别按返回或下一步,那么您将转到主页类框架,在本例中为 BlankPage。

import tkinter as tk
from tkinter import ttk

class Program(tk.Tk):        
    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)

        tk.Tk.iconbitmap(self, default = "")
        tk.Tk.wm_title(self, "")

        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 (Add, BlankPage):

            frame = F(container, self)
            self.frames[F] = frame
            frame.grid(row = 0, column = 0, sticky = "nsew")

        self.show_frame(Add)

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

class Add(tk.Frame):

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

        innerFrame = tk.Frame(self)
        innerFrame.place(relx=.5, rely=.5, anchor="c", relwidth=1.0, relheight=1.0)

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

        name = tk.Label(innerFrame, text = "User")
        name.grid(row=0, sticky="NE")

        pagename = tk.Label(innerFrame, text = "Label")
        pagename.grid(row=0, sticky="N")

        next = ttk.Button(innerFrame, text = "Next", command = self.changePage)
        next.grid(row=2, sticky="E")

        back = ttk.Button(innerFrame, text = "Back", command = self.changePage)
        back.grid(row=2, sticky="W")

########################################################################################################### 

        self.pageThree = tk.Frame(innerFrame)
        self.pageThree.grid(row=1)

        self.pageThree.grid_rowconfigure(0, weight=1)
        self.pageThree.grid_columnconfigure(0, weight=1)

        pagename = tk.Label(self.pageThree, text = "Page 3")
        pagename.grid(row=0, sticky="N")

########################################################################################################### 

        self.pageTwo = tk.Frame(innerFrame)
        self.pageTwo.grid(row=1)

        self.pageTwo.grid_rowconfigure(0, weight=1)
        self.pageTwo.grid_columnconfigure(0, weight=1)

        pagename = tk.Label(self.pageTwo, text = "Page 2")
        pagename.grid(row=0, sticky="N")

########################################################################################################### 

        self.pageOne = tk.Frame(innerFrame)
        self.pageOne.grid(row=1)

        self.pageOne.grid_rowconfigure(0, weight=1)
        self.pageOne.grid_columnconfigure(0, weight=1)

        pagename = tk.Label(self.pageOne, text = "Page 1")
        pagename.grid(row=0, sticky="N")

########################################################################################################### 

    def changePage(self,buttonBool):
        pages = [self.pageOne,self.pageTwo,self.pageThree]
        #find current raised page and set to variable 'current'
        position = pages.index(current)
        if (postion==0 and buttonBool==False) or (postion==len(pages)-1 and buttonBool==True):
            show_frame(BlankPage)
        elif buttonBool==True:
            pages[position+1].tkraise()
        else:
            pages[position-1].tkraise()


class BlankPage(tk.Frame):

    def __init__(self, parent, controller):

        tk.Frame.__init__(self, parent)


app = Program()
app.state('zoomed')
app.mainloop()

changePage 功能是我的尝试,我将如何完成它?

【问题讨论】:

那么,您希望能够在一个可以与其他框架切换的框架内切换框架(即:嵌套切换框架?) @BryanOakley 差不多,但我还需要内部框架(self.pageX 框架)按照它们在页面列表中出现的顺序来回切换。 【参考方案1】:

你已经很接近让这一切正常工作了,在看了我自己之后,我找不到任何(不是过于复杂)的方法来找出最上面的 Frame 所以最好只保留一个记录当前位置:

def __init__(self, parent, controller):

    ...

    self.position = 0 #the index of the pages list

要将buttonBool 传递给changePage,您可以something from here(Tlapička 在我看来是最好的解决方案,因为lambda 表达式会使代码行太长)

def __init__(self, parent, controller):
    ...
    # button commands don't have an event but sometimes you use these callbacks for both .bind and buttons
    # so having event=None makes it work for both.
    def go_next(event=None):
        self.changePage(True)

    next = ttk.Button(innerFrame, text = "Next", command = go_next)
    next.grid(row=2, sticky="E")

    def go_back(event=None):
        self.changePage(False)

    back = ttk.Button(innerFrame, text = "Back", command = go_back)
    back.grid(row=2, sticky="W")

    ...

通过这两个(并将self.position 实现为changePage),您可以完成您最初要求的操作,下面的所有内容都是我所说的code reviewer。


虽然使用布尔值会起作用,但这种处理回调的额外参数的策略允许您将 any 参数传递给changePage,因此它可能会简化changePage 中的条件,如果它得到页面变化(所以 1 或 -1):

    def go_next(event=None):
        self.changePage(1)

    next = ttk.Button(innerFrame, text = "Next", command = go_next)
    next.grid(row=2, sticky="E")

    def go_back(event=None):
        self.changePage(-1)

    back = ttk.Button(innerFrame, text = "Back", command = go_back)
    back.grid(row=2, sticky="W") 

    #this is for the last suggestion
    self.nextButton = next
    self.backButton = back
    ...

然后changePage 可能看起来像这样,尽管我不确定如果您更改为无效页面,self.position 会发生什么:

def changePage(self,change):
    pages = [self.pageOne,self.pageTwo,self.pageThree]
    new_position = self.position + change
    if (new_postion < 0) or (new_postion <= len(pages)):
        show_frame(BlankPage)
        #not sure how you would handle the new position here
    else:
        pages[new_position].tkraise()
        self.position = new_position

更好的是,如果您保留对nextback 按钮的引用,您可以通过config 来表示这是结束/开始:

def changePage(self,change):
    pages = [self.pageOne,self.pageTwo,self.pageThree]
    new_position = self.position + change
    if (0 <= new_postion < len(pages)):
        pages[new_position].tkraise()
        self.position = new_position
    else:
        show_frame(BlankPage)

    if new_position+1 >= len(pages):
        self.nextButton.config(text="End") #, state=tk.DISABLED)
    else:
        self.nextButton.config(text="Next") #, state=tk.NORMAL)

    if new_position-1 < 0:
        self.backButton.config(text="First") #, state=tk.DISABLED)
    else:
        self.backButton.config(text="Back") #, state=tk.NORMAL)

这样即使内容没有任何指示,您也会知道何时到达终点。 (或者您可以禁用按钮以防止过去)

【讨论】:

以上是关于tkinter - 使用按钮在帧之间来回切换的主要内容,如果未能解决你的问题,请参考以下文章

如何从启动页面在不同的 tkinter 画布之间切换并返回子画布中的启动页面

无法使用按钮和自定义数据更新 Tkinter matplotlib 图

来回切换 JS 按钮

使用tkinter切换按钮文本

在 qmetry 中的驱动程序之间来回切换

使用 Tkinter 中的菜单栏在页面之间切换