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 21 Python
Python使用SocketServer模块编写基本服务器程序的教程
Jul 12 Python
python基础之包的导入和__init__.py的介绍
Jan 08 Python
python 给DataFrame增加index行名和columns列名的实现方法
Jun 08 Python
Pycharm 2019 破解激活方法图文详解
Oct 11 Python
通过实例解析Python调用json模块
Dec 11 Python
Python Numpy,mask图像的生成详解
Feb 19 Python
python通过对字典的排序,对json字段进行排序的实例
Feb 27 Python
简单了解Django项目应用创建过程
Jul 06 Python
解决TensorFlow调用Keras库函数存在的问题
Jul 06 Python
python调用有道智云API实现文件批量翻译
Oct 10 Python
Python insert() / append() 用法 Leetcode实战演示
Mar 31 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中的fopen()函数用打开文件模式说明
2013/06/20 PHP
php中替换字符串中的空格为逗号','的方法
2014/06/09 PHP
php实现html标签闭合检测与修复方法
2015/07/09 PHP
PHP获取二维数组中某一列的值集合
2015/12/25 PHP
实例分析PHP将字符串转换成数字的方法
2019/01/27 PHP
PHP数组遍历的几种常见方式总结
2019/02/15 PHP
jQuery实现的类flash菜单效果代码
2010/05/17 Javascript
原生JS实现加入收藏夹的代码
2013/10/24 Javascript
js获取视频时长代码
2014/04/10 Javascript
node.js中的fs.writeFile方法使用说明
2014/12/14 Javascript
JS清除选择内容的方法
2015/01/29 Javascript
jQuery实现的超酷苹果风格图标滑出菜单效果代码
2015/09/16 Javascript
Augularjs-起步详解
2016/07/08 Javascript
微信小程序 开发指南详解
2016/09/27 Javascript
javascript中replace使用方法总结
2017/03/01 Javascript
JavaScript数据结构与算法之二叉树实现查找最小值、最大值、给定值算法示例
2019/03/01 Javascript
Vue filter 过滤当前时间 实现实时更新效果
2019/12/20 Javascript
Vue 组件复用多次自定义参数操作
2020/07/27 Javascript
js实现无缝轮播图插件封装
2020/07/31 Javascript
在Python中使用poplib模块收取邮件的教程
2015/04/29 Python
Python爬取京东的商品分类与链接
2016/08/26 Python
python音频处理用到的操作的示例代码
2017/10/27 Python
Python中print和return的作用及区别解析
2019/05/05 Python
Python求正态分布曲线下面积实例
2019/11/20 Python
logging level级别介绍
2020/02/21 Python
Python如何重新加载模块
2020/07/29 Python
jupyter notebook快速入门及使用详解
2020/11/13 Python
Giuseppe Zanotti美国官方网站:将鞋履视为高级时装般精心制作
2018/02/06 全球购物
欧洲领先的火车票和大巴票预订平台:Trainline
2018/12/26 全球购物
大学生饮食配送创业计划书
2014/01/04 职场文书
公司道歉信范文
2014/01/09 职场文书
县长群众路线对照检查材料思想汇报
2014/10/02 职场文书
教师师德师风整改措施
2014/10/24 职场文书
红楼梦读书笔记
2015/06/25 职场文书
宣传稿格式范文
2015/07/23 职场文书
MYSQL 表的全面总结
2021/11/11 MySQL