Python GUI編程之tkinter模塊Toplevel控件實現(xiàn)搭建父子窗口
Toplevel控件搭建父子窗口
最近,用Python給單位里用的“智慧食堂”系統(tǒng)編制了一個餐卡充值文件生成器,自動匹配餐卡號并快速生成導入數(shù)據(jù)用的Excel表格,截圖如下:
使用tkinter Toplevel控件彈出子窗口,用作設(shè)置備注的子窗口。在編程過程中,邊學邊寫探索到不少新知識,簡單介紹如下:
最簡明的父子窗口框架
創(chuàng)建一個主窗口、一個子窗口,各放一個按鈕,代碼如下:
import win32api, tkinter as tk def _toplevel(): top = tk.Toplevel(root) top.title("Toplevel Window") W,H=400,300 top.geometry(f'{W}x{H}+{(X-W)//2}+{(Y-H)//2}') btn_Close = tk.Button(top, text="Close", command=top.destroy) btn_Close.pack() if __name__=='__main__': # 創(chuàng)建主窗口 root = tk.Tk() root.title("Main Window") # 獲取windows系統(tǒng)桌面分辨率 X,Y=win32api.GetSystemMetrics(0),win32api.GetSystemMetrics(1) W,H=600,480 root.geometry(f'{W}x{H}+{(X-W)//2}+{(Y-H)//2}') # 創(chuàng)建一個打開Toplevel窗口的按鈕 btn_Open = tk.Button(root, text="Open Toplevel", command=_toplevel) btn_Open.pack() # 運行Tkinter事件循環(huán) root.mainloop()
上述代碼的缺點是主窗口上的Open按鈕可以反復點擊打開多個子窗口,要想辦法按需要來屏蔽它的點擊功能。
改進屏蔽和開放按鈕
以下代碼可以調(diào)整按鈕的使用狀態(tài):tk.DISABLED、tk.NORMAL
button.config(state=tk.DISABLED)
button.config(state=tk.NORMAL)
打開子窗口時,Open按鈕的狀態(tài)改為tk.DISABLED,此時已無法點擊了。
import win32api, tkinter as tk class TopWindow: def __init__(self, parent): top = self.top = tk.Toplevel(parent) top.title("Toplevel Window") W,H=400,300 top.geometry(f'{W}x{H}+{(X-W)//2}+{(Y-H)//2}') btn_Close = tk.Button(top, text="Close", command=self.on_close) btn_Close.pack() def on_close(self): btn_Open.config(state=tk.NORMAL) self.top.destroy() def on_open(): TopWindow(root) btn_Open.config(state=tk.DISABLED) if __name__=='__main__': root = tk.Tk() root.title("Main Window") X,Y=win32api.GetSystemMetrics(0),win32api.GetSystemMetrics(1) W,H=600,480 root.geometry(f'{W}x{H}+{(X-W)//2}+{(Y-H)//2}') btn_Open = tk.Button(root, text="Open Toplevel", command=on_open) btn_Open.pack() root.mainloop()
改進子窗口始終在主窗口之上
top.transient(root) # 設(shè)置Toplevel窗口始終在主窗口root的上方
import win32api, tkinter as tk class TopWindow: def __init__(self, parent): top = self.top = tk.Toplevel(parent) top.title("Toplevel Window") W,H=400,300 top.geometry(f'{W}x{H}+{(X-W)//2}+{(Y-H)//2}') top.transient(root) # 設(shè)置Toplevel窗口始終在主窗口上方 btn_Close = tk.Button(top, text="Close", command=self.on_close) btn_Close.pack() def on_close(self): btn_Open.config(state=tk.NORMAL) self.top.destroy() def on_open(): TopWindow(root) btn_Open.config(state=tk.DISABLED) if __name__=='__main__': root = tk.Tk() root.title("Main Window") X,Y=win32api.GetSystemMetrics(0),win32api.GetSystemMetrics(1) W,H=600,480 root.geometry(f'{W}x{H}+{(X-W)//2}+{(Y-H)//2}') btn_Open = tk.Button(root, text="Open Toplevel", command=on_open) btn_Open.pack() root.mainloop()
另外一種方法也能設(shè)置子窗口永遠在前:
top.wm_attributes('-topmost', True) # 設(shè)置Toplevel窗口在所有窗口的上方
兩種方法的區(qū)別在于后者是全局的設(shè)置,它使得子窗口在操作系統(tǒng)中所有窗口的上面,包括其它應(yīng)用程序的窗口。
如下圖,請比較一下與上一張截圖的效果有啥區(qū)別:
改進增加子窗口的關(guān)閉協(xié)議
如下圖,直接點擊子窗口右上關(guān)閉按鈕,只觸發(fā)窗口默認的top.destroy事件。這樣關(guān)閉子窗口后,主窗口的按鈕狀態(tài)并不能恢復;以下代碼使得子窗口的"WM_DELETE_WINDOW"關(guān)閉協(xié)議綁定了自定義的關(guān)閉事件self.onclose:
top.protocol("WM_DELETE_WINDOW", self.on_close)
完整代碼如下:
import win32api, tkinter as tk class TopWindow: def __init__(self, parent): top = self.top = tk.Toplevel(parent) top.title("Toplevel Window") W,H=400,300 top.geometry(f'{W}x{H}+{(X-W)//2}+{(Y-H)//2}') top.transient(root) top.protocol("WM_DELETE_WINDOW", self.on_close) btn_Close = tk.Button(top, text="Close", command=self.on_close) btn_Close.pack() def on_close(self): btn_Open.config(state=tk.NORMAL) self.top.destroy() def on_open(): TopWindow(root) btn_Open.config(state=tk.DISABLED) if __name__=='__main__': root = tk.Tk() root.title("Main Window") X,Y=win32api.GetSystemMetrics(0),win32api.GetSystemMetrics(1) W,H=600,480 root.geometry(f'{W}x{H}+{(X-W)//2}+{(Y-H)//2}') btn_Open = tk.Button(root, text="Open Toplevel", command=on_open) btn_Open.pack() root.mainloop()
改進使子窗口長獲焦點
top.grab_set() # 確保Toplevel窗口長獲焦點
使用這個方法,前面提到的按鈕狀態(tài)的切換以及子窗口綁定關(guān)閉協(xié)議的代碼都不需要了,非常簡潔。top.grab_set()
配合top.transient(root)
共同使用(如下標注紅色部分),效果最佳:
import win32api, tkinter as tk class TopWindow: def __init__(self, parent): top = self.top = tk.Toplevel(parent) top.title("Toplevel Window") W,H=400,300 top.geometry(f'{W}x{H}+{(X-W)//2}+{(Y-H)//2}') top.grab_set() top.transient(root) btn_Close = tk.Button(top, text="Close", command=top.destroy) btn_Close.pack() def on_open(): TopWindow(root) if __name__=='__main__': root = tk.Tk() root.title("Main Window") X,Y=win32api.GetSystemMetrics(0),win32api.GetSystemMetrics(1) W,H=600,480 root.geometry(f'{W}x{H}+{(X-W)//2}+{(Y-H)//2}') btn_Open = tk.Button(root, text="Open Toplevel", command=on_open) btn_Open.pack() root.mainloop()
源代碼復制框如下:
import win32api, tkinter as tk class TopWindow: def __init__(self, parent): top = self.top = tk.Toplevel(parent) top.title("Toplevel Window") W,H=400,300 top.geometry(f'{W}x{H}+{(X-W)//2}+{(Y-H)//2}') top.grab_set() top.transient(root) btn_Close = tk.Button(top, text="Close", command=top.destroy) btn_Close.pack() def on_open(): TopWindow(root) if __name__=='__main__': root = tk.Tk() root.title("Main Window") X,Y=win32api.GetSystemMetrics(0),win32api.GetSystemMetrics(1) W,H=600,480 root.geometry(f'{W}x{H}+{(X-W)//2}+{(Y-H)//2}') btn_Open = tk.Button(root, text="Open Toplevel", command=on_open) btn_Open.pack() root.mainloop()
總結(jié)
通過對toplevel控件的編程操練,掌握了tkinter子窗口的調(diào)用方法,了解了topleve的多種特殊方法、響應(yīng)事件以及綁定協(xié)議。
到此這篇關(guān)于Python GUI編程之tkinter模塊Toplevel控件實現(xiàn)搭建父子窗口的文章就介紹到這了,更多相關(guān)Python Toplevel搭建父子窗口內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
關(guān)于python中plt.hist參數(shù)的使用詳解
今天小編就為大家分享一篇關(guān)于python中plt.hist參數(shù)的使用詳解,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-11-11Python利用numpy實現(xiàn)三層神經(jīng)網(wǎng)絡(luò)的示例代碼
這篇文章主要介紹了Python利用numpy實現(xiàn)三層神經(jīng)網(wǎng)絡(luò)的示例代碼,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2021-04-04Python Dict 到 Dataclass實現(xiàn)高效數(shù)據(jù)訪問與管理的兩種方式(推薦)
本文介紹了Python中的字典和DataClass兩種數(shù)據(jù)結(jié)構(gòu),并探討了如何將字典轉(zhuǎn)換為DataClass,字典適用于鍵值對存儲,感興趣的朋友一起看看吧2024-12-12