用Python开发图形界面和程序时,经常会对图形界面的搭建感到失望,或许是由于对图形界面不熟悉的原因吧,总之一想到图形界面,就感觉会很费时、费力,编程的积极性大幅下降。最近,尝试用Tkinter创建了一个简便的图形界面,这个过程果然和原先想的不差多少,搭建窗口界面,调整位置布局,确实很费时费力,与其它可视化编程工具的差距实在太过悬殊。但是既然已经开始了,就尝试把这个界面做成一个简单的模板吧,以后如果遇到有类似的窗口应用需要开发,也好直接拿来就用,减少启动阻力。如果你也正好有这样的困惑,参考本文中的程序代码或许可以让你省点心力。
空谈无益,上图 show 代码:
TKinter图形界面简易窗口
上面的图片是启动后的初始窗口界面,用于显示LOGO或者文字内容(序号1),这个窗口适合处理一些简单的功能,本案例中的功能设定是,往输入框(序号3)中输入一段文字,点击[开始](序号4),或按回车后,功能函数会根据 ', '对输入的文字内容进行分割并保存到列表框中,之后可以在展开的窗口界面中点击[处理选中内容],或者[处理全部内容]按钮,就可以调用多进程执行字数统计的函数。当然这里只是一个最简单的示例演示,你也完全可以用于处理更多的场景,比如说,你可以在输入框输入需要搜索的文字,或者需要下载的网址等内容。
输入框右侧的开始按钮(序号4)绑定了相应函数的调用,表示对这个内容进行处理; 如果这一个简单的窗口不能满足你的需求,还有更多的内容需要操作,可以点击旁边的红色小按钮(序号5),就可以展开这个窗口,展开后的内容如下图所示:
TKinter图形界面展开窗口
输入框的下方,添加了一排功能按钮(序号6),可以设定调用不同的函数,以实现程序的相应功能,你可以通过复制源代码,重新设定变量名,等一些简单的操作,达到增加或者减少按钮的效果,也可以调整按钮的间距和字体等显示效果,使用起来会比重头开始搭建要方便不少。
功能按钮下方是一个显示详细内容的列表框(序号7),这个列表框也已经绑定了滚动条(序号8),这里可以用于显示正在处理的内容,比如说可以作为播放列表,显示即将播放的歌曲和状态,或者也可以作为下载列表,用于显示目前各内容的下载以及完成情况等,本文的末尾附有一个根据这个模板进行完善的Youtube视频下载程序,列表框中,各行内容的显示效果可以在程序中通过调整文字内容,以及设定不同的颜色加以完善。
接下来,在列表框的下方,也有一排操作按键(序号9)专门用于对列表框中的内容进行操作,比如说,选中,反向选择,删除等,本案例中已经设定了与相关列表框操作函数的调用,你可以通过简单的调整,就可以完成相应功能的设定。
最后,是状态栏(序号10),用于显示各个功能执行过程中的状态,完全可以通过非常容易的变量替换,再结合你的实际需要进行调整。
除此之外,本案例中还添加了键盘事件与功能函数的绑定,当焦点落在输入框的时候,按下control键会自动清空内容,可以更方便的让你在按下control+v 粘贴快捷键之前,不需要对输入框的内容进行删除操作 , 另外回车键也已经和开始按钮的功能联动,当你输入内容,并按下回车键的时候,会自动执行开始任务。
完整的代码如下:
"""
Title : TKinter Template with Thread and Multiprocessing
Author: Le Miaokai
Date : 2022-10-21
Email : LeMiaokai@Gmail.com
"""
# 导入基本模块
import os, sys
# 调用tkinter模块
from tkinter import *
from tkinter import messagebox, filedialog
# 调用多线程模块
from threading import Thread
# 调用多进程模块
from multiprocessing import Pool, freeze_support
# 调用ctypes模块,以便在运行时隐藏控制窗口,但是在启动的时候,会有控制框闪过。
# 如果用auto_py_to_exe 可完全解决起动时控制框闪过的问题。
import ctypes
# 运行程序的时候,隐藏控制窗口
whnd = ctypes.windll.kernel32.GetConsoleWindow()
if whnd != 0:
ctypes.windll.user32.ShowWindow(whnd, 0)
ctypes.windll.kernel32.CloseHandle(whnd)
# 通过多线程添加内容到列表框中
def put_item_to_list(event=''):
# 启用多线程,将内容添加到列表中
t_1 = Thread(target=append_to_list)
t_1.start()
# 只要调用了添加到列表中的功能,就将窗口放大。
root.geometry('900x550')
more_BT["text"]=' ^ '
# 添加内容到列表中
def append_to_list():
text = input_text.get()
if len(text) == 0:
messagebox.showinfo("提示:", "请检查输入框中的内容,多个信息请以 ,分隔!")
else:
# 将输入的内容,去除空格后,以 , 进行分割,并存入到列表中。
text = text.strip().replace(',', ',').split(',')
# 循环添加内容到列表框
for item_id, item in enumerate(text):
add_link_to_listbox(item_id, item)
# 添加内容完成后恢复窗口中的按钮状态
button_state(state = "normal")
# 添加单个项目到listbox中
def add_link_to_listbox(item_id, item):
global g_ytlink_dict
# 本案例中item_id对应列表框中的序号,作为索引
item_id = list_box.size()
# 如果索引内容已经添加,则在状态栏显示,当前item的状态参数,
if item_id in g_info_dict and g_info_dict[item_id]!=[]:
status_info["text"] = f"| {
g_info_dict[item_id][3]}"
else:
# item_id, 作为内容的索引号, 每个索引号对应的内容为 [列表框中的显示位置序号,项目内容,是否已经完成,以及当前状态] 等
g_info_dict[item_id] = [list_box.size(), item, False, '']
# 将当前信息,添加到列表框中, 输出的序号,需要 list_box.size() + 1, 未尾添加可以直接用END
list_box.insert(END, f"{
str(list_box.size()+1).zfill(3)} . {
item}")
# 回调函数,返回结果, 在用多进程任务完成后,自动调用本函数
def collectMyResult(result):
global g_info_dict, g_count
item_id = result[1]
# 显示多进程中已经完成任务所返回的结果信息
if result[0] == True:
# 处理成功后,更新状态:
g_info_dict[item_id][2] = True
g_info_dict[item_id][3] = '处理完成,总字数为{}个。'.format(result[2])
# 处理完成后,变更列表框中的状态
tasks_status(item_id)
else:
g_info_dict[item_id][3] = "处理失败!"
tasks_status(item_id)
# 在状态样栏中显示目前已经处理完成的计数
g_count += 1
status_info["text"] = f"|总计完成数量 : {
g_count}"
# 处理全部列表框中的内容
def threading_all_tasks():
# 先全部选中
select_all()
# 调用处理选中内容的函数
threading_tasks()
# 设定并启用进程池处理需要执行的任务
def threading_tasks():
# 调用处理列表中选中内容的函数,需要创建一个多线程,否则窗口会无响应
v_l = Thread(target=multiprocess_pool)
v_l.start()
# 设定函数,通过多进程池,分配添加多进程任务