python tkinter詳解,python3.6 +tkinter GUI編程 實現界面化的文本處理工具

 2023-11-19 阅读 28 评论 0

摘要:更新: python tkinter詳解、2017.07.17  補充滾動條、win批處理拉起py 2017.08.13  新增自定義圖標 常用python編程軟件。? --------原創? ? ??blogs: ?? http://www.cnblogs.com/chenyuebai ? ?-------- ? 一、背景: 1.工作中自己及同事在查數據庫、測試接

更新:

python tkinter詳解、2017.07.17  補充滾動條、win批處理拉起py

2017.08.13  新增自定義圖標

常用python編程軟件。?

--------原創? ? ??blogs: ?? http://www.cnblogs.com/chenyuebai ? ?--------

?

一、背景:

1.工作中自己及同事在查數據庫、測試接口時需要對一些字符串或json串作預處理,目前這些問題網上均有在線轉換的工具,但很繁雜,可能需要打開幾個網頁窗口;

2.之前給妹子做的文本處理工具(http://www.cnblogs.com/chenyuebai/p/6999561.html)是基于cmd命令行的,不太友好;

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

?

基于以上,了解到python自帶的tkinter庫可以初步滿足UI的需求,業余時間做了個圖形化工具,涉及窗口、文本、按鈕、標簽、菜單、菜單樹、滾動條、文件處理、界面布局等;

下文將梳理從零到完成的全過程,作為自己GUI學習的一個總結;

ps:后面版本間隙有時間的話想試試用pyQt來做。。tkinter做出的界面確實。。。23333

工具界面截圖:     

?

?

?二、實現

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()
復制代碼

運行結果:

- - - - - - - - - - - -?- - - - - - - - - - - -?- - - - - - - - - - - -?- - - - - - - - - - - -

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

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

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

運行結果:

整理下代碼:

#################################################################
#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/7657887self.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放置在指定位置,并展示;

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

代碼中的: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_NUMcurrent_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 + 1else: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 timeLOG_LINE_NUM = 0class 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_NUMcurrent_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 + 1else: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()

?

上面例子代碼的執行結果:

?

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

有問題歡迎留言交流;

后面有時間會補充用windows批處理拉起python代碼,這樣就可以像普通軟件一樣使用這個小工具了;

?

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文本框的值,可以使滾動條長度完美貼合文本框

效果:

?

三、其他

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,寫入

Set ws = CreateObject("Wscript.Shell")
ws.run "cmd /c start.bat",vbhide

此時雙擊該vbs腳本,即可拉起軟件界面,且隱藏cmd控制臺界面;

?

2. 暫時木有了。。

后面項目間隙有可能會研究下robotFramework~

也有可能會試著用pyQt重寫下這個界面

先到這了;

?

?

2017.07.17

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

3.自定義圖標

python打開工具時,左上角默認為tkinter默認圖標任務欄為python默認圖標;

查了下,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")

效果:

左上角:?? ? ? ? ??? 底側任務欄:?

?

附目錄結構:

轉載于:https://www.cnblogs.com/hackpig/p/8120307.html

版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。

原文链接:https://hbdhgg.com/4/179667.html

发表评论:

本站为非赢利网站,部分文章来源或改编自互联网及其他公众平台,主要目的在于分享信息,版权归原作者所有,内容仅供读者参考,如有侵权请联系我们删除!

Copyright © 2022 匯編語言學習筆記 Inc. 保留所有权利。

底部版权信息