【发布时间】:2012-06-19 11:55:36
【问题描述】:
我一直在研究 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()
【问题讨论】:
-
那么问题是什么?虽然是的,但您可以自行回答,但您应该通过发布答案作为问题的答案来做到这一点。
-
只是为了澄清:我创建此线程不是为了提出问题,而是为了发布我在许多网站上看到的常见问题的解决方案。我需要创建的第一个真正的 GUI 程序是“安装向导”,经过数小时的挖掘,我在网上找不到任何示例代码。所以当我终于让我的“概念证明”工作时,我决定在这里发布它,希望它可以帮助其他人学习 tkinter :)
-
@Mikael Hartzell:Donal 的观点是:您正在做的事情的正确程序是发明一个问题,然后将您的答案作为实际答案提供。因此,您的问题可以很简单,例如“如何制作一个类似向导的窗口,该窗口可以在带有下一个和后退按钮的帧之间循环?”。然后,您在原始问题中输入的所有代码都会转到答案。
-
好的,下次会做的:) 这是我的第一篇文章,所以我不知道网站的网络礼仪:)
-
如果你想在程序中放置一些交互式的东西,比如用户进行测验,或者用户在文本字段中输入他们的名字,那么你会把它放在这个程序的什么地方?例如。我想在第二个屏幕上进行测验。我应该把它放在 create_widgets_for_second_screen 函数中吗?
标签: navigation python-3.x window tkinter