python3.6 +tkinter GUI编程 实现界面化的文本处理工具(推荐)


Posted in Python onDecember 20, 2017

更新:

2017.07.17

补充滚动条、win批处理拉起py

2017.08.13

新增自定义图标

一、背景:

1.工作中自己及同事在查数据库、测试接口时需要对一些字符串或json串作预处理,目前这些问题网上均有在线转换的工具,但很繁杂,可能需要打开几个网页窗口;

2.之前做的文本处理工具是基于cmd命令行的,不太友好;

3.自己做的一些小工具也基本都是命令行执行的,也想接触下GUI;

基于以上,了解到python自带的tkinter库可以初步满足UI的需求,业余时间做了个图形化工具,涉及窗口、文本、按钮、标签、菜单、菜单树、滚动条、文件处理、界面布局等;

下文将梳理从零到完成的全过程,作为自己GUI学习的一个总结;

ps:后面版本间隙有时间的话想试试用pyQt来做。。tkinter做出的界面确实。。。23333

工具界面截图:

   

python3.6 +tkinter GUI编程 实现界面化的文本处理工具(推荐)

二、实现

1.安装所需要的库 ps:环境是win7+python 3.6,tkinter是py的标准库,即:如不涉及EXCEL处理,可跳过此步骤;使用python处理Excel表格,后面有时间会单独整理

(1)et-xmlfile

openpyxl安装需要依赖,工具里有涉及处理EXCEL(xlsx),需要用到openpyxl库;

(2)jdcal

同上

(3)openpyxl

处理EXCEL(xlsx)

(4)xlrd

读取EXCEL(xls)

(5)xlwt

写入EXCEL(xls)

(6)xltils

配合上面两个库对已存在表格进行修改

2.新建父窗口(可理解为界面的最底层)

#################################################################
#author: 陈月白
#_blogs: http://www.cnblogs.com/chenyuebai/
#################################################################
from tkinter import *
def gui_start():
 init_window = Tk()  #实例化出一个父窗口
 init_window.mainloop() #父窗口进入事件循环,可以理解为保持窗口运行,否则界面不展示
gui_start()

运行结果:

python3.6 +tkinter GUI编程 实现界面化的文本处理工具(推荐)

- - - - - - - - - - - -- - - - - - - - - - - -- - - - - - - - - - - -- - - - - - - - - - - -

运行会弹出上图所示的空白窗口,这里我们还可以修改窗口默认大小、默认弹出位置、窗口名、父窗口颜色、虚化等等;

init_window.title("文本处理工具 by: 陈月白")
 init_window.geometry('290x160+10+10')  #290 160为窗口大小,+10 +10 定义窗口弹出时的默认展示位置
 init_window["bg"] = "pink"     #窗口背景色,其他背景色见:blog.csdn.net/chl0000/article/details/7657887
 init_window.attributes("-alpha",0.8)  #虚化 值越小虚化程度越高

注意要加在 init_window.mainloop() 之前;

运行结果:

python3.6 +tkinter GUI编程 实现界面化的文本处理工具(推荐)

整理下代码:

#################################################################
#author: 陈月白
#_blogs: http://www.cnblogs.com/chenyuebai/
#################################################################
from tkinter import *import hashlib
class MY_GUI():
 def __init__(self,init_window_name):
  self.init_window_name = init_window_name
 #设置窗口
 def set_init_window(self):
  self.init_window_name.title("文本处理工具_v1.2 by: 陈月白")  #窗口名
  self.init_window_name.geometry('1068x680+10+10')     #290 160为窗口大小,+10 +10 定义窗口弹出时的默认展示位置
  self.init_window_name["bg"] = "pink"       #窗口背景色,其他背景色见:blog.csdn.net/chl0000/article/details/7657887
  self.init_window_name.attributes("-alpha",0.9)     #虚化,值越小虚化程度越高
def gui_start():
 init_window = Tk()    #实例化出一个父窗口
 ZMJ_PORTAL = MY_GUI(init_window)
 # 设置根窗口默认属性
 ZMJ_PORTAL.set_init_window()
 init_window.mainloop()   #父窗口进入事件循环,可以理解为保持窗口运行,否则界面不展示
gui_start()

先到这,有时间再整理。。

--------------------------------------------------------------------------------

继续。

3.父窗口完成后,即可基于父窗口创建其他组件

下面以“字符串转MD5”为例,介绍数据读取、按钮、布局、事件触发、后台转换处理、界面展示结果;

(1)标签

标签可以使用tkinter里的Label()方法,生成标签,括号内可带入其他属性参数;
生成标签后需使用grid()或者pack()方法使其展示;

#注:tkinter对于同一个父窗口,只可允许使用一种布局函数;另外还有个place()方法,不过目前我还没用过;

self.init_data_label = Label(self.init_window_name, text="待处理数据")
self.init_data_label.grid(row=0, column=0)
self.result_data_label = Label(self.init_window_name, text="输出结果")
self.result_data_label.grid(row=0, column=12)

这里正好提一下grid(),说下我的理解。grid()方法是tkinter库自带的布局函数,他可以将父窗口分割成类似一个Excel表格,对单个组件按照参数中传递的row、column放置在指定位置,并展示;

下图红框部分,代表整个父窗口界面:

python3.6 +tkinter GUI编程 实现界面化的文本处理工具(推荐)

代码中的:self.init_data_label.grid(row=0, column=0)

代表将“init_data_label”这个标签放置在页面的第一行,第一列的位置(即左上角),并展示;

(2)文本框
tkinter库中的Text()方法,可以创建一个文本框,用于数据的录入和结果展示;Text()方法可以传入其他参数值,用于定义如背景颜色,前景色,字体,字号、字色等

self.init_data_Text = Text(self.init_window_name, width=67, height=35) #原始数据录入框
self.init_data_Text.grid(row=1, column=0, rowspan=10, columnspan=10)
self.result_data_Text = Text(self.init_window_name, width=70, height=49) #处理结果展示
self.result_data_Text.grid(row=1, column=12, rowspan=15, columnspan=10)

self.init_data_Text.grid(row=1, column=0, rowspan=10, columnspan=10) #"rowspan=10" 是grid()方法的一个参数,用于指定该组件(init_data_Text)占用的行数,同理columnspan用于指定占用列数;

(3)按钮

按钮的创建可以使用Button()方法实现,可自定义按钮大小,宽度,按钮文本,背景色,以及需要触发的事件;

#按钮
self.str_trans_to_md5_button = Button(self.init_window_name, text="字符串转MD5", bg="lightblue", width=10,command=self.str_trans_to_md5) # 调用内部方法 加()为直接调用
self.str_trans_to_md5_button.grid(row=1, column=11)

触发事件:在定义按钮时,使用command=functionname这个参数来指定;当按钮被点击,就会调用command后的方法,从而完成事件的触发;

这里有个小坑。。。就是command后跟函数名时,不可加括号,否则在代码执行时,就会触发该函数;

举个例子,上面贴的代码中“command=self.str_trans_to_md5”若写为“command=self.str_trans_to_md5()”,该gui_test.py在执行时便会调用类中的self.str_trans_to_md5()方法,而不是在点击按钮时才触发;

(4)事件代码:后台的处理

step3中在定义按钮时,会选择触发一个事件(或称为函数),函数的实现涉及:从界面文本框中读取待处理数据---逻辑处理---界面结果文本框展示

code:

def str_trans_to_md5(self):
  src = self.init_data_Text.get(1.0,END).strip().replace("\n","").encode()
  #print("src =",src)
  if src:
   try:
    myMd5 = hashlib.md5()
    myMd5.update(src)
    myMd5_Digest = myMd5.hexdigest()
    #print(myMd5_Digest)
    #输出到界面
    self.result_data_Text.delete(1.0,END)
    self.result_data_Text.insert(1.0,myMd5_Digest)
#从第一行开始
   except:
    self.result_data_Text.delete(1.0,END)
    self.result_data_Text.insert(1.0,"字符串转MD5失败")
  else:
   print("ERROR") #界面左下角会有日志框,支持动态打印,下面会提到

读取待处理数据:对之前定义的self.init_data_Text(待处理数据文本框)可使用tkinter库中自带的get()方法,获取文本框中的内容,str类型;

逻辑处理:MD5加密,不展开了,从网上找的例子照着敲;

界面结果文本框展示:对获取的字符串处理后,即可使用Text.insert(index,strdata)方法插入结果文本框:self.result_data_Text;

插入前建议先清理下,Text.delete(1.0,END)代表将文本框从第一行删除至最后一行,即清空;

(5)日志打印

和上面没啥区别,直接贴代码了~

def get_current_time(self):
  current_time = time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time()))
  return current_time


 #日志动态打印
 def write_log_to_Text(self,logmsg):
  global LOG_LINE_NUM
  current_time = self.get_current_time()
  logmsg_in = str(current_time) +" " + str(logmsg) + "\n"  #换行
  if LOG_LINE_NUM <= 7:
   self.log_data_Text.insert(END, logmsg_in)
   LOG_LINE_NUM = LOG_LINE_NUM + 1
  else:
   self.log_data_Text.delete(1.0,2.0)
   self.log_data_Text.insert(END, logmsg_in)
  #移动光标
  self.log_data_Text.focus_force()

整体的例子代码如下:

#################################################################
#author: 陈月白
#_blogs: http://www.cnblogs.com/chenyuebai/
#################################################################
from tkinter import *
import hashlib
import time
LOG_LINE_NUM = 0
class MY_GUI():
 def __init__(self,init_window_name):
  self.init_window_name = init_window_name
 #设置窗口
 def set_init_window(self):
  self.init_window_name.title("文本处理工具_v1.2 by: 陈月白")   #窗口名
  #self.init_window_name.geometry('320x160+10+10')       #290 160为窗口大小,+10 +10 定义窗口弹出时的默认展示位置
  self.init_window_name.geometry('1068x681+10+10')
  #self.init_window_name["bg"] = "pink"         #窗口背景色,其他背景色见:blog.csdn.net/chl0000/article/details/7657887
  #self.init_window_name.attributes("-alpha",0.9)       #虚化,值越小虚化程度越高
  #标签
  self.init_data_label = Label(self.init_window_name, text="待处理数据")
  self.init_data_label.grid(row=0, column=0)
  self.result_data_label = Label(self.init_window_name, text="输出结果")
  self.result_data_label.grid(row=0, column=12)
  self.log_label = Label(self.init_window_name, text="日志")
  self.log_label.grid(row=12, column=0)
  #文本框
  self.init_data_Text = Text(self.init_window_name, width=67, height=35) #原始数据录入框
  self.init_data_Text.grid(row=1, column=0, rowspan=10, columnspan=10)
  self.result_data_Text = Text(self.init_window_name, width=70, height=49) #处理结果展示
  self.result_data_Text.grid(row=1, column=12, rowspan=15, columnspan=10)
  self.log_data_Text = Text(self.init_window_name, width=66, height=9) # 日志框
  self.log_data_Text.grid(row=13, column=0, columnspan=10)
  #按钮
  self.str_trans_to_md5_button = Button(self.init_window_name, text="字符串转MD5", bg="lightblue", width=10,command=self.str_trans_to_md5) # 调用内部方法 加()为直接调用
  self.str_trans_to_md5_button.grid(row=1, column=11)
 #功能函数
 def str_trans_to_md5(self):
  src = self.init_data_Text.get(1.0,END).strip().replace("\n","").encode()
  #print("src =",src)
  if src:
   try:
    myMd5 = hashlib.md5()
    myMd5.update(src)
    myMd5_Digest = myMd5.hexdigest()
    #print(myMd5_Digest)
    #输出到界面
    self.result_data_Text.delete(1.0,END)
    self.result_data_Text.insert(1.0,myMd5_Digest)
    self.write_log_to_Text("INFO:str_trans_to_md5 success")
   except:
    self.result_data_Text.delete(1.0,END)
    self.result_data_Text.insert(1.0,"字符串转MD5失败")
  else:
   self.write_log_to_Text("ERROR:str_trans_to_md5 failed")
 #获取当前时间
 def get_current_time(self):
  current_time = time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time()))
  return current_time
 #日志动态打印
 def write_log_to_Text(self,logmsg):
  global LOG_LINE_NUM
  current_time = self.get_current_time()
  logmsg_in = str(current_time) +" " + str(logmsg) + "\n"  #换行
  if LOG_LINE_NUM <= 7:
   self.log_data_Text.insert(END, logmsg_in)
   LOG_LINE_NUM = LOG_LINE_NUM + 1
  else:
   self.log_data_Text.delete(1.0,2.0)
   self.log_data_Text.insert(END, logmsg_in)
def gui_start():
 init_window = Tk()    #实例化出一个父窗口
 ZMJ_PORTAL = MY_GUI(init_window)
 # 设置根窗口默认属性
 ZMJ_PORTAL.set_init_window()
 init_window.mainloop()   #父窗口进入事件循环,可以理解为保持窗口运行,否则界面不展示
gui_start()

上面例子代码的执行结果:

python3.6 +tkinter GUI编程 实现界面化的文本处理工具(推荐)

大概就是这些,其他功能、按钮大同小异,就不赘述了;

有问题欢迎留言交流;

后面有时间会补充用windows批处理拉起python代码,这样就可以像普通软件一样使用这个小工具了;

python3.6 +tkinter GUI编程 实现界面化的文本处理工具(推荐)

2017.07.14

--------------------------------------------------------------------------------

继续。

(6)滚动条

对于展示长文本,需要在Text文本框侧翼(或下方)提供滚动条;tkinter库中提供Scrollbar()方法创建一个滚动条

# 滚动条
self.result_data_scrollbar_y = Scrollbar(self.init_window_name)    #创建纵向滚动条
self.result_data_scrollbar_y.config(command=self.result_data_Text.yview)  #将创建的滚动条通过command参数绑定到需要拖动的Text上
self.result_data_Text.config(yscrollcommand=self.result_data_scrollbar_y.set) #Text反向绑定滚动条
self.result_data_scrollbar_y.grid(row=1, column=23, rowspan=15, sticky='NS')

ps1:滚动条与待绑定的组件(Text或其他)时,需要二者相互绑定,从而达到拖动任意一方,对应方同步移动;

ps2:grid()中rowspan的值最好取Text文本框的值,可以使滚动条长度完美贴合文本框

效果:

python3.6 +tkinter GUI编程 实现界面化的文本处理工具(推荐)

三、其他

1.windows批处理拉起python

py代码完成后,为方便使用,可以使用windows批处理脚本拉起python代码

common_tools_gui.py所在目录下新建start.bat,写入 @python common_tools_gui.py %* @pause

@pause可以保持代码一直处于运行状态,而不是控制台一闪而过;

#python需配置在环境变量中,或者使用绝对路径。。

但也会带来一个问题,就是在双击这个批处理时,软件界面出来的同时,会附带一个黑色的cmd控制台窗口;

百度了一下,可以使用windows的.vbs拉起批处理来规避:

common_tools_gui.py所在目录下新建start_my_gui.vbs,写入

import ctypes 
ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID("myappid")

此时双击该vbs脚本,即可拉起软件界面,且隐藏cmd控制台界面;

python3.6 +tkinter GUI编程 实现界面化的文本处理工具(推荐)

2. 暂时木有了。。

后面项目间隙有可能会研究下robotFramework~

也有可能会试着用pyQt重写下这个界面

先到这了;

2017.07.17

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

3.自定义图标

python打开工具时,左上角默认为tkinter默认图标

python3.6 +tkinter GUI编程 实现界面化的文本处理工具(推荐)

,任务栏为python默认图标;

python3.6 +tkinter GUI编程 实现界面化的文本处理工具(推荐)

查了下,python的tkinter库支持自定义图标:py文件当前目录下制作ico图标文件(https://www.ico.la/),父窗口使用iconbitmap()方法,指定该文件即可;

self.init_window_name.iconbitmap('text_processing_tools.ico')
 #指定界面图标

中途有个坑,就是仅左上角生效,但windows下方的任务栏无效;

百度之,大概意思是文本工具的py文件运行时,windows认为弹出的工具窗口是python解释器的衍生程序(子程序?),即默认仍使用pythpn解释器的图标;

需要在代码中指定弹出窗口的AppUserModelID即可:

import ctypes 
ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID("myappid")

效果:

左上角:python3.6 +tkinter GUI编程 实现界面化的文本处理工具(推荐) 底侧任务栏:python3.6 +tkinter GUI编程 实现界面化的文本处理工具(推荐)

附目录结构:

python3.6 +tkinter GUI编程 实现界面化的文本处理工具(推荐)

2017.08.13

Python 相关文章推荐
python定时检查某个进程是否已经关闭的方法
May 20 Python
fastcgi文件读取漏洞之python扫描脚本
Apr 23 Python
Python读取sqlite数据库文件的方法分析
Aug 07 Python
Python处理CSV与List的转换方法
Apr 19 Python
Tensorflow 训练自己的数据集将数据直接导入到内存
Jun 19 Python
Python中遍历列表的方法总结
Jun 27 Python
python之MSE、MAE、RMSE的使用
Feb 24 Python
Python爬虫爬取电影票房数据及图表展示操作示例
Mar 27 Python
Pyinstaller 打包发布经验总结
Jun 02 Python
pycharm 关掉syntax检查操作
Jun 09 Python
python线程优先级队列知识点总结
Feb 28 Python
matplotlib之pyplot模块实现添加子图subplot的使用
Apr 25 Python
浅谈Python实现Apriori算法介绍
Dec 20 #Python
利用Python如何生成hash值示例详解
Dec 20 #Python
python 3.6 tkinter+urllib+json实现火车车次信息查询功能
Dec 20 #Python
python实现神经网络感知器算法
Dec 20 #Python
Python代码实现KNN算法
Dec 20 #Python
详解appium+python 启动一个app步骤
Dec 20 #Python
浅谈Django自定义模板标签template_tags的用处
Dec 20 #Python
You might like
PHP使用strtotime计算两个给定日期之间天数的方法
2015/03/18 PHP
PHP内置加密函数详解
2016/11/20 PHP
需要做特殊处理的DOM元素属性的访问
2010/11/05 Javascript
关于Javascript模块化和命名空间管理的问题说明
2010/12/06 Javascript
js 利用className得到对象的实现代码
2011/11/15 Javascript
js读写cookie实现一个底部广告浮层效果的两种方法
2013/12/29 Javascript
HTML页面登录时的JS验证方法
2014/05/28 Javascript
深入浅析JavaScript中prototype和proto的关系
2015/11/15 Javascript
jqGrid表格应用之新增与删除数据附源码下载
2015/12/02 Javascript
理解javascript中的严格模式
2016/02/01 Javascript
jQuery插件ajaxfileupload.js实现上传文件
2020/10/23 Javascript
AngularJS使用ng-repeat指令实现下拉框
2016/08/23 Javascript
最全面的百度地图JavaScript离线版开发
2016/09/10 Javascript
jQuery动态追加页面数据以及事件委托详解
2017/05/06 jQuery
Vue.js 踩坑记之双向绑定
2018/05/03 Javascript
Vue 报错TypeError: this.$set is not a function 的解决方法
2018/12/17 Javascript
Auto.JS实现抖音刷宝等刷视频app,自动点赞,自动滑屏,自动切换视频功能
2020/05/08 Javascript
Vue触发input选取文件点击事件操作
2020/08/07 Javascript
vue keep-alive的简单总结
2021/01/25 Vue.js
js实现验证码干扰(静态)
2021/02/22 Javascript
[00:58]2016年国际邀请赛勇士令状宣传片
2016/06/01 DOTA
简析Python的闭包和装饰器
2016/02/26 Python
python3编码问题汇总
2016/09/06 Python
Python编程之event对象的用法实例分析
2017/03/23 Python
Python利用递归实现文件的复制方法
2018/10/27 Python
python tkinter canvas 显示图片的示例
2019/06/13 Python
python调用函数、类和文件操作简单实例总结
2019/11/29 Python
Python基于WordCloud制作词云图
2019/11/29 Python
python实现交并比IOU教程
2020/04/16 Python
美体小铺美国官网:The Body Shop美国
2017/11/10 全球购物
乌克兰在线电子产品商店:MTA
2019/11/14 全球购物
华为python面试题
2016/05/03 面试题
公司市场部岗位职责
2013/12/02 职场文书
领导检查欢迎词
2014/01/14 职场文书
中学生演讲稿
2014/04/26 职场文书
个人租房协议书范本
2014/09/30 职场文书