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 相关文章推荐
50行代码实现贪吃蛇(具体思路及代码)
Apr 27 Python
分析Python编程时利用wxPython来支持多线程的方法
Apr 07 Python
Python 异常处理的实例详解
Sep 11 Python
Python使用pylab库实现绘制直方图功能示例
Jun 01 Python
从0开始的Python学习016异常
Apr 08 Python
python3中使用__slots__限定实例属性操作分析
Feb 14 Python
Python基于codecs模块实现文件读写案例解析
May 11 Python
Python使用jupyter notebook查看ipynb文件过程解析
Jun 02 Python
Python 如何创建一个线程池
Jul 28 Python
Python性能测试工具Locust安装及使用
Dec 01 Python
使用python爬取抖音app视频的实例代码
Dec 01 Python
Python数组变形的几种实现方法
May 30 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_Flame(Version:Progress)的原代码
2006/10/09 PHP
php str_pad 函数用法简介
2009/07/11 PHP
发款php蜘蛛统计插件只要有mysql就可用
2010/10/12 PHP
php接口数据加密、解密、验证签名
2015/03/12 PHP
thinkPHP5项目中实现QQ第三方登录功能
2017/10/20 PHP
在Laravel5中正确设置文件权限的方法
2019/05/22 PHP
Laravel框架Auth用户认证操作实例分析
2019/09/29 PHP
JavaScript 代码压缩工具小结
2012/02/27 Javascript
文本框中禁止非数字字符输入比如手机号码、邮编
2013/08/19 Javascript
js 日期比较相关天数代码
2014/04/02 Javascript
js中substr,substring,indexOf,lastIndexOf,split,replace的用法详解
2015/11/09 Javascript
jquery实现鼠标悬浮停止轮播特效
2020/08/20 Javascript
Bootstrap源码解读下拉菜单(4)
2016/12/23 Javascript
快速掌握jQuery插件开发
2017/01/19 Javascript
react-router4 嵌套路由的使用方法
2017/07/24 Javascript
关于微信小程序登录的那些事
2019/01/08 Javascript
vue发送websocket请求和http post请求的实例代码
2019/07/11 Javascript
跟老齐学Python之传说中的函数编写条规
2014/10/11 Python
浅析Python中元祖、列表和字典的区别
2016/08/17 Python
Python 基础知识之字符串处理
2017/01/06 Python
Python读写docx文件的方法
2018/05/08 Python
Python3.6.0+opencv3.3.0人脸检测示例
2018/05/25 Python
Python使用wget实现下载网络文件功能示例
2018/05/31 Python
Python函数中参数是传递值还是引用详解
2019/07/02 Python
jupyter notebook实现显示行号
2020/04/13 Python
Pytorch mask-rcnn 实现细节分享
2020/06/24 Python
基于python实现删除指定文件类型
2020/07/21 Python
Python限制内存和CPU使用量的方法(Unix系统适用)
2020/08/04 Python
关于python scrapy中添加cookie踩坑记录
2020/11/17 Python
python字典与json转换的方法总结
2020/12/28 Python
迪斯尼商品官方网站:ShopDisney
2016/08/01 全球购物
英国最大的海报商店:GB Posters
2018/03/20 全球购物
Cinque网上商店:德国服装品牌
2019/03/17 全球购物
美国在线面料商店:Fashion Fabrics Club
2020/01/31 全球购物
生活小常识广播稿
2014/09/16 职场文书
山楂树之恋观后感
2015/06/11 职场文书