亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

python3.6 +tkinter GUI編程 實(shí)現(xiàn)界面化的文本處理

系統(tǒng) 1846 0

更新:

2017.07.17  補(bǔ)充滾動(dòng)條、win批處理拉起py

2017.08.13  新增自定義圖標(biāo)

一、背景:

1.工作中自己及同事在查數(shù)據(jù)庫(kù)、測(cè)試接口時(shí)需要對(duì)一些字符串或json串作預(yù)處理,目前這些問(wèn)題網(wǎng)上均有在線轉(zhuǎn)換的工具,但很繁雜,可能需要打開(kāi)幾個(gè)網(wǎng)頁(yè)窗口;

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

3.自己做的一些小工具也基本都是命令行執(zhí)行的,也想接觸下GUI;

基于以上,了解到python自帶的tkinter庫(kù)可以初步滿足UI的需求,業(yè)余時(shí)間做了個(gè)圖形化工具,涉及窗口、文本、按鈕、標(biāo)簽、菜單、菜單樹(shù)、滾動(dòng)條、文件處理、界面布局等;

下文將梳理從零到完成的全過(guò)程,作為自己GUI學(xué)習(xí)的一個(gè)總結(jié);

ps:后面版本間隙有時(shí)間的話想試試用pyQt來(lái)做。。tkinter做出的界面確實(shí)。。。23333

工具界面截圖:     

python3.6 +tkinter GUI編程 實(shí)現(xiàn)界面化的文本處理工具(推薦)_第1張圖片

二、實(shí)現(xiàn)

1.安裝所需要的庫(kù) ps:環(huán)境是win7+python 3.6,tkinter是py的標(biāo)準(zhǔn)庫(kù),即: 如不涉及EXCEL處理,可跳過(guò)此步驟 ;使用python處理Excel表格,后面有時(shí)間會(huì)單獨(dú)整理

(1)et-xmlfile  openpyxl安裝需要依賴,工具里有涉及處理EXCEL(xlsx),需要用到openpyxl庫(kù);

(2)jdcal    同上

(3)openpyxl  處理EXCEL(xlsx)

(4)xlrd     讀取EXCEL(xls)

(5)xlwt     寫入EXCEL(xls)

(6)xltils    配合上面兩個(gè)庫(kù)對(duì)已存在表格進(jìn)行修改

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

            
#################################################################
#author: 陳月白
#_blogs: http://www.cnblogs.com/chenyuebai/
#################################################################
from tkinter import *
def gui_start():
 init_window = Tk()  #實(shí)例化出一個(gè)父窗口
 init_window.mainloop() #父窗口進(jìn)入事件循環(huán),可以理解為保持窗口運(yùn)行,否則界面不展示
gui_start()
          

運(yùn)行結(jié)果:

python3.6 +tkinter GUI編程 實(shí)現(xiàn)界面化的文本處理工具(推薦)_第2張圖片

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

運(yùn)行會(huì)彈出上圖所示的空白窗口,這里我們還可以修改窗口默認(rèn)大小、默認(rèn)彈出位置、窗口名、父窗口顏色、虛化等等;

            
init_window.title("文本處理工具 by: 陳月白")
 init_window.geometry('290x160+10+10')  #290 160為窗口大小,+10 +10 定義窗口彈出時(shí)的默認(rèn)展示位置
 init_window["bg"] = "pink"     #窗口背景色,其他背景色見(jiàn):blog.csdn.net/chl0000/article/details/7657887
 init_window.attributes("-alpha",0.8)  #虛化 值越小虛化程度越高
          

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

運(yùn)行結(jié)果:

python3.6 +tkinter GUI編程 實(shí)現(xiàn)界面化的文本處理工具(推薦)_第3張圖片

整理下代碼:

            
#################################################################
#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
 #設(shè)置窗口
 def set_init_window(self):
  self.init_window_name.title("文本處理工具_(dá)v1.2 by: 陳月白")  #窗口名
  self.init_window_name.geometry('1068x680+10+10')     #290 160為窗口大小,+10 +10 定義窗口彈出時(shí)的默認(rèn)展示位置
  self.init_window_name["bg"] = "pink"       #窗口背景色,其他背景色見(jiàn):blog.csdn.net/chl0000/article/details/7657887
  self.init_window_name.attributes("-alpha",0.9)     #虛化,值越小虛化程度越高
def gui_start():
 init_window = Tk()    #實(shí)例化出一個(gè)父窗口
 ZMJ_PORTAL = MY_GUI(init_window)
 # 設(shè)置根窗口默認(rèn)屬性
 ZMJ_PORTAL.set_init_window()
 init_window.mainloop()   #父窗口進(jìn)入事件循環(huán),可以理解為保持窗口運(yùn)行,否則界面不展示
gui_start()
          

先到這,有時(shí)間再整理。。

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

繼續(xù)。

3.父窗口完成后,即可基于父窗口創(chuàng)建其他組件

下面以“字符串轉(zhuǎn)MD5”為例,介紹數(shù)據(jù)讀取、按鈕、布局、事件觸發(fā)、后臺(tái)轉(zhuǎn)換處理、界面展示結(jié)果;

(1)標(biāo)簽

標(biāo)簽可以使用tkinter里的Label()方法,生成標(biāo)簽,括號(hào)內(nèi)可帶入其他屬性參數(shù);
生成標(biāo)簽后需使用grid()或者pack()方法使其展示;  

#注:tkinter對(duì)于同一個(gè)父窗口,只可允許使用一種布局函數(shù);另外還有個(gè)place()方法,不過(guò)目前我還沒(méi)用過(guò);

            
self.init_data_label = Label(self.init_window_name, text="待處理數(shù)據(jù)")
self.init_data_label.grid(row=0, column=0)
self.result_data_label = Label(self.init_window_name, text="輸出結(jié)果")
self.result_data_label.grid(row=0, column=12)
          

這里正好提一下grid(),說(shuō)下我的理解。grid()方法是tkinter庫(kù)自帶的布局函數(shù),他可以將父窗口分割成類似一個(gè)Excel表格,對(duì)單個(gè)組件按照參數(shù)中傳遞的row、column放置在指定位置,并展示;

下圖紅框部分,代表整個(gè)父窗口界面:

python3.6 +tkinter GUI編程 實(shí)現(xiàn)界面化的文本處理工具(推薦)_第4張圖片

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

代表將“init_data_label”這個(gè)標(biāo)簽放置在頁(yè)面的第一行,第一列的位置(即左上角),并展示;

(2)文本框
tkinter庫(kù)中的Text()方法,可以創(chuàng)建一個(gè)文本框,用于數(shù)據(jù)的錄入和結(jié)果展示;Text()方法可以傳入其他參數(shù)值,用于定義如背景顏色,前景色,字體,字號(hào)、字色等

            
self.init_data_Text = Text(self.init_window_name, width=67, height=35) #原始數(shù)據(jù)錄入框
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) #處理結(jié)果展示
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()方法的一個(gè)參數(shù),用于指定該組件(init_data_Text)占用的行數(shù),同理columnspan用于指定占用列數(shù);

(3)按鈕

按鈕的創(chuàng)建可以使用Button()方法實(shí)現(xiàn),可自定義按鈕大小,寬度,按鈕文本,背景色,以及需要觸發(fā)的事件;

            
#按鈕
self.str_trans_to_md5_button = Button(self.init_window_name, text="字符串轉(zhuǎn)MD5", bg="lightblue", width=10,command=self.str_trans_to_md5) # 調(diào)用內(nèi)部方法 加()為直接調(diào)用
self.str_trans_to_md5_button.grid(row=1, column=11)
          

觸發(fā)事件:在定義按鈕時(shí),使用command=functionname這個(gè)參數(shù)來(lái)指定;當(dāng)按鈕被點(diǎn)擊,就會(huì)調(diào)用command后的方法,從而完成事件的觸發(fā);

這里有個(gè)小坑。。。就是command后跟函數(shù)名時(shí),不可加括號(hào),否則在代碼執(zhí)行時(shí),就會(huì)觸發(fā)該函數(shù);

舉個(gè)例子,上面貼的代碼中“command=self.str_trans_to_md5”若寫為“command=self.str_trans_to_md5()”,該gui_test.py在執(zhí)行時(shí)便會(huì)調(diào)用類中的self.str_trans_to_md5()方法,而不是在點(diǎn)擊按鈕時(shí)才觸發(fā);

(4)事件代碼:后臺(tái)的處理

step3中在定義按鈕時(shí),會(huì)選擇觸發(fā)一個(gè)事件(或稱為函數(shù)),函數(shù)的實(shí)現(xiàn)涉及:從界面文本框中讀取待處理數(shù)據(jù)---邏輯處理---界面結(jié)果文本框展示

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)  #從第一行開(kāi)始
   except:
    self.result_data_Text.delete(1.0,END)
    self.result_data_Text.insert(1.0,"字符串轉(zhuǎn)MD5失敗")
  else:
   print("ERROR") #界面左下角會(huì)有日志框,支持動(dòng)態(tài)打印,下面會(huì)提到
          

讀取待處理數(shù)據(jù) :對(duì)之前定義的self.init_data_Text(待處理數(shù)據(jù)文本框)可使用tkinter庫(kù)中自帶的get()方法,獲取文本框中的內(nèi)容,str類型;

邏輯處理 :MD5加密,不展開(kāi)了,從網(wǎng)上找的例子照著敲;

界面結(jié)果文本框展示 :對(duì)獲取的字符串處理后,即可使用Text.insert(index,strdata)方法插入結(jié)果文本框:self.result_data_Text;

插入前建議先清理下,Text.delete(1.0,END)代表將文本框從第一行刪除至最后一行,即清空;

(5)日志打印

和上面沒(méi)啥區(qū)別,直接貼代碼了~

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


 #日志動(dòng)態(tài)打印
 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)
  #移動(dòng)光標(biāo)
  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
 #設(shè)置窗口
 def set_init_window(self):
  self.init_window_name.title("文本處理工具_(dá)v1.2 by: 陳月白")   #窗口名
  #self.init_window_name.geometry('320x160+10+10')       #290 160為窗口大小,+10 +10 定義窗口彈出時(shí)的默認(rèn)展示位置
  self.init_window_name.geometry('1068x681+10+10')
  #self.init_window_name["bg"] = "pink"         #窗口背景色,其他背景色見(jiàn):blog.csdn.net/chl0000/article/details/7657887
  #self.init_window_name.attributes("-alpha",0.9)       #虛化,值越小虛化程度越高
  #標(biāo)簽
  self.init_data_label = Label(self.init_window_name, text="待處理數(shù)據(jù)")
  self.init_data_label.grid(row=0, column=0)
  self.result_data_label = Label(self.init_window_name, text="輸出結(jié)果")
  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) #原始數(shù)據(jù)錄入框
  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) #處理結(jié)果展示
  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="字符串轉(zhuǎn)MD5", bg="lightblue", width=10,command=self.str_trans_to_md5) # 調(diào)用內(nèi)部方法 加()為直接調(diào)用
  self.str_trans_to_md5_button.grid(row=1, column=11)
 #功能函數(shù)
 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,"字符串轉(zhuǎn)MD5失敗")
  else:
   self.write_log_to_Text("ERROR:str_trans_to_md5 failed")
 #獲取當(dāng)前時(shí)間
 def get_current_time(self):
  current_time = time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time()))
  return current_time
 #日志動(dòng)態(tài)打印
 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()    #實(shí)例化出一個(gè)父窗口
 ZMJ_PORTAL = MY_GUI(init_window)
 # 設(shè)置根窗口默認(rèn)屬性
 ZMJ_PORTAL.set_init_window()
 init_window.mainloop()   #父窗口進(jìn)入事件循環(huán),可以理解為保持窗口運(yùn)行,否則界面不展示
gui_start()
          

上面例子代碼的執(zhí)行結(jié)果:

python3.6 +tkinter GUI編程 實(shí)現(xiàn)界面化的文本處理工具(推薦)_第5張圖片

大概就是這些,其他功能、按鈕大同小異,就不贅述了;

有問(wèn)題歡迎留言交流;

后面有時(shí)間會(huì)補(bǔ)充用windows批處理拉起python代碼,這樣就可以像普通軟件一樣使用這個(gè)小工具了;

python3.6 +tkinter GUI編程 實(shí)現(xiàn)界面化的文本處理工具(推薦)_第6張圖片

2017.07.14

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

繼續(xù)。

(6)滾動(dòng)條

對(duì)于展示長(zhǎng)文本,需要在Text文本框側(cè)翼(或下方)提供滾動(dòng)條;tkinter庫(kù)中提供Scrollbar()方法創(chuàng)建一個(gè)滾動(dòng)條

            
# 滾動(dòng)條
self.result_data_scrollbar_y = Scrollbar(self.init_window_name)    #創(chuàng)建縱向滾動(dòng)條
self.result_data_scrollbar_y.config(command=self.result_data_Text.yview)  #將創(chuàng)建的滾動(dòng)條通過(guò)command參數(shù)綁定到需要拖動(dòng)的Text上
self.result_data_Text.config(yscrollcommand=self.result_data_scrollbar_y.set) #Text反向綁定滾動(dòng)條
self.result_data_scrollbar_y.grid(row=1, column=23, rowspan=15, sticky='NS') 
          

ps1:滾動(dòng)條與待綁定的組件(Text或其他)時(shí),需要二者相互綁定,從而達(dá)到拖動(dòng)任意一方,對(duì)應(yīng)方同步移動(dòng);

ps2:grid()中rowspan的值最好取Text文本框的值,可以使?jié)L動(dòng)條長(zhǎng)度完美貼合文本框

效果:

python3.6 +tkinter GUI編程 實(shí)現(xiàn)界面化的文本處理工具(推薦)_第7張圖片

三、其他

1.windows批處理拉起python

py代碼完成后,為方便使用,可以使用windows批處理腳本拉起python代碼

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

@pause可以保持代碼一直處于運(yùn)行狀態(tài),而不是控制臺(tái)一閃而過(guò);  #python需配置在環(huán)境變量中,或者使用絕對(duì)路徑。。

但也會(huì)帶來(lái)一個(gè)問(wèn)題,就是在雙擊這個(gè)批處理時(shí),軟件界面出來(lái)的同時(shí),會(huì)附帶一個(gè)黑色的cmd控制臺(tái)窗口;

百度了一下,可以使用windows的.vbs拉起批處理來(lái)規(guī)避:

common_tools_gui.py所在目錄下新建start_my_gui.vbs,寫入

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

此時(shí)雙擊該vbs腳本,即可拉起軟件界面,且隱藏cmd控制臺(tái)界面;

2. 暫時(shí)木有了。。

后面項(xiàng)目間隙有可能會(huì)研究下robotFramework~

也有可能會(huì)試著用pyQt重寫下這個(gè)界面

先到這了;

2017.07.17

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

3.自定義圖標(biāo)

python打開(kāi)工具時(shí),左上角默認(rèn)為tkinter默認(rèn)圖標(biāo)

,任務(wù)欄為python默認(rèn)圖標(biāo);

查了下,python的tkinter庫(kù)支持自定義圖標(biāo):py文件當(dāng)前目錄下制作ico圖標(biāo)文件(https://www.ico.la/),父窗口使用iconbitmap()方法,指定該文件即可;

            
self.init_window_name.iconbitmap('text_processing_tools.ico')
 #指定界面圖標(biāo)
          

中途有個(gè)坑,就是僅左上角生效,但windows下方的任務(wù)欄無(wú)效;

百度之,大概意思是文本工具的py文件運(yùn)行時(shí),windows認(rèn)為彈出的工具窗口是python解釋器的衍生程序(子程序?),即默認(rèn)仍使用pythpn解釋器的圖標(biāo);

需要在代碼中指定彈出窗口的AppUserModelID即可:

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

效果:

左上角: 底側(cè)任務(wù)欄:

附目錄結(jié)構(gòu):

2017.08.13


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對(duì)您有幫助就好】

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長(zhǎng)會(huì)非常 感謝您的哦!!!

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論
主站蜘蛛池模板: 亚洲视频a| 欧美成视频一theporn | a国产视频| 久久婷婷色一区二区三区 | 中文字幕国产 | 天天综合天天添夜夜添狠狠添 | 中文字幕在线免费播放 | 久久老色鬼天天综合网观看 | 一个色在线 | 欧美高清在线视频一区二区 | 香蕉一区 | 曰本还a大片免费无播放器 曰本黄色录像 | 亚洲精品自产拍在线观看 | 夜色视频一区二区三区 | 夜夜操国产| 国产亚洲一区二区三区啪 | 天天透天天操 | 天天色天天拍 | 亚洲欧美一区二区三区综合 | 久久精品精品 | 四虎久久久 | 欧美一区二区三区视频在线观看 | 亚洲加勒比久久88色综合一区 | 精品人人做人人爽久久久 | 久久人人精品 | 国产午夜精品一二区理论影院 | 久久久久中文字幕 | 国产专区日韩精品欧美色 | 99久久综合狠狠综合久久一区 | 国产成人免费a在线视频色戒 | 久久香蕉国产线看观看精品蕉 | 特级毛片全部免费播放a一级 | av毛片免费看| 久久久久久岛国免费网站 | 精品福利视频第一 | 国产成人高清亚洲一区久久 | 99久久综合狠狠综合久久aⅴ | 日韩欧美亚洲中字幕在线播放 | 久久精品这里有 | se94se欧美综合色 | 久久精品国产主播一区二区 |