我一直在研究python3中的tkinter,发现很难在网上找到好的文档和答案。为了帮助其他遇到相同问题的人,我决定为一个简单的问题发布一个解决方案,这个问题似乎没有在线文档。
问题:创建一个类似向导的程序,该程序为用户提供一系列窗口,用户可以在窗口之间移动,单击"下一步"和"后退 - 按钮"。
解决方案是:
- 创建一个根窗口。
- 创建尽可能多的框架,以便向用户显示窗口。将所有框架附加到根窗口。
- 用所需的所有小部件填充每个框架。
- 填充所有帧后,使用
grid_forget()
方法隐藏每个帧,但保留第一个帧不隐藏,使其变为可见帧。框架上的所有子小部件将与框架一起隐藏。 - 当用户单击窗口上的"下一步"或"后退"按钮时,调用隐藏其他帧(带
grid_forget()
)并使所需帧可见(带grid()
)的子例程。 - 如果希望程序结束,请使用根窗口的 destroy - 方法。
因此,您将创建一个窗口并在其上显示不同的框架。
(顺便说一下,开始学习tkinter的最佳地点是:http://www.tkdocs.com/tutorial/index.html)
下面是 Python3 中的一个示例实现。它有3个简单的窗口,每个窗口都有一个文本标签和两个按钮来浏览不同的窗口。
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# Creates three "windows" that the user can navigate through using Back and Next - buttons.
import tkinter
import tkinter.ttk
def create_widgets_in_first_frame():
# Create the label for the frame
first_window_label = tkinter.ttk.Label(first_frame, text='Window 1')
first_window_label.grid(column=0, row=0, pady=10, padx=10, sticky=(tkinter.N))
# Create the button for the frame
first_window_quit_button = tkinter.Button(first_frame, text = "Quit", command = quit_program)
first_window_quit_button.grid(column=0, row=1, pady=10, sticky=(tkinter.N))
first_window_next_button = tkinter.Button(first_frame, text = "Next", command = call_second_frame_on_top)
first_window_next_button.grid(column=1, row=1, pady=10, sticky=(tkinter.N))
def create_widgets_in_second_frame():
# Create the label for the frame
second_window_label = tkinter.ttk.Label(second_frame, text='Window 2')
second_window_label.grid(column=0, row=0, pady=10, padx=10, sticky=(tkinter.N))
# Create the button for the frame
second_window_back_button = tkinter.Button(second_frame, text = "Back", command = call_first_frame_on_top)
second_window_back_button.grid(column=0, row=1, pady=10, sticky=(tkinter.N))
second_window_next_button = tkinter.Button(second_frame, text = "Next", command = call_third_frame_on_top)
second_window_next_button.grid(column=1, row=1, pady=10, sticky=(tkinter.N))
def create_widgets_in_third_frame():
# Create the label for the frame
third_window_label = tkinter.ttk.Label(third_frame, text='Window 3')
third_window_label.grid(column=0, row=0, pady=10, padx=10, sticky=(tkinter.N))
# Create the button for the frame
third_window_back_button = tkinter.Button(third_frame, text = "Back", command = call_second_frame_on_top)
third_window_back_button.grid(column=0, row=1, pady=10, sticky=(tkinter.N))
third_window_quit_button = tkinter.Button(third_frame, text = "Quit", command = quit_program)
third_window_quit_button.grid(column=1, row=1, pady=10, sticky=(tkinter.N))
def call_first_frame_on_top():
# This function can be called only from the second window.
# Hide the second window and show the first window.
second_frame.grid_forget()
first_frame.grid(column=0, row=0, padx=20, pady=5, sticky=(tkinter.W, tkinter.N, tkinter.E))
def call_second_frame_on_top():
# This function can be called from the first and third windows.
# Hide the first and third windows and show the second window.
first_frame.grid_forget()
third_frame.grid_forget()
second_frame.grid(column=0, row=0, padx=20, pady=5, sticky=(tkinter.W, tkinter.N, tkinter.E))
def call_third_frame_on_top():
# This function can only be called from the second window.
# Hide the second window and show the third window.
second_frame.grid_forget()
third_frame.grid(column=0, row=0, padx=20, pady=5, sticky=(tkinter.W, tkinter.N, tkinter.E))
def quit_program():
root_window.destroy()
###############################
# Main program starts here :) #
###############################
# Create the root GUI window.
root_window = tkinter.Tk()
# Define window size
window_width = 200
window_heigth = 100
# Create frames inside the root window to hold other GUI elements. All frames must be created in the main program, otherwise they are not accessible in functions.
first_frame=tkinter.ttk.Frame(root_window, width=window_width, height=window_heigth)
first_frame['borderwidth'] = 2
first_frame['relief'] = 'sunken'
first_frame.grid(column=0, row=0, padx=20, pady=5, sticky=(tkinter.W, tkinter.N, tkinter.E))
second_frame=tkinter.ttk.Frame(root_window, width=window_width, height=window_heigth)
second_frame['borderwidth'] = 2
second_frame['relief'] = 'sunken'
second_frame.grid(column=0, row=0, padx=20, pady=5, sticky=(tkinter.W, tkinter.N, tkinter.E))
third_frame=tkinter.ttk.Frame(root_window, width=window_width, height=window_heigth)
third_frame['borderwidth'] = 2
third_frame['relief'] = 'sunken'
third_frame.grid(column=0, row=0, padx=20, pady=5, sticky=(tkinter.W, tkinter.N, tkinter.E))
# Create all widgets to all frames
create_widgets_in_third_frame()
create_widgets_in_second_frame()
create_widgets_in_first_frame()
# Hide all frames in reverse order, but leave first frame visible (unhidden).
third_frame.grid_forget()
second_frame.grid_forget()
# Start tkinter event - loop
root_window.mainloop()
因为您冒昧地将答案作为问题发布。 我想发表评论作为答案,并建议也许您应该将其贡献给 TkDocs(单击他们的"关于"选项卡,他们谈论为该网站做出贡献)。
我认为如果该网站要用更多的例子来改进,而不是把这个网站变成一本食谱,那就更好了。 我认为你也可以为Active State配方做出贡献,它们似乎是Tcl/Tk火炬的载体,所以Tkinter的东西在那里也很有意义。
感谢您的工作 - 我将其用作此示例的灵感,虽然在内容方面非常轻巧,但这是一种很酷的方法,可以制作任意数量的窗口,您可以在其中切换。您可以移动下一个和后退按钮的位置,将它们变成箭头,随心所欲。
from tkinter import *
master=Tk()
class makeframe(object):
def __init__(self,i):
self.i=i
self.frame=Frame(master)
self.nextbutton=Button(self.frame,text='next',command=self.next)
self.nextbutton.grid(column=2,row=0)
self.backbutton=Button(self.frame,text='back',command=self.back)
self.backbutton.grid(column=0,row=0)
self.label=Label(self.frame,text='%i'%(self.i+1)).grid(column=1,row=0)
def next(self):
self.frame.grid_forget()
p[self.i+1].frame.grid()
def back(self):
self.frame.grid_forget()
p[self.i-1].frame.grid()
n=7
p=[0]*n
for i in range(n):
p[i]=makeframe(i)
p[0].frame.grid()
p[0].backbutton.config(state=DISABLED)
p[-1].nextbutton.config(state=DISABLED)