python: Parent-child form operations
# encoding: utf-8 # 版權所有 2024 ©塗聚文有限公司 # 許可資訊查看:言語成了邀功的功臣,還需要行爲每日來值班嗎? # 描述: 主、子表單 窗體傳值 Parent-child form operations # Author : geovindu,Geovin Du 塗聚文. # IDE : PyCharm 2023.1 python 3.11 # OS : windows 10 # Datetime : 2024/10/24 20:09 # User : geovindu # Product : PyCharm # Project : IctGame # File : ui/main.py # explain : 學習 from tkinter import * import tkinter as tk from tkinter import Tk, Menu from tkinter.ttk import * from tkinter.messagebox import showinfo from tkinter.messagebox import askyesno from tkinter.messagebox import askyesnocancel # https://docs.python.org/3/library/tkinter.messagebox.html import datetime import re import time import ctypes u32 = ctypes.windll.user32 class MainWindow(tk.Tk): """ 主表單 """ # ts = time.time() reverseFlag = False def __init__(self): """ """ super().__init__() self.title("Main Window") self.geometry('{}x{}'.format(1350, 900)) self.button = tk.Button(self, text=" Child New Window", command=self.openChildNewWindow) self.button.pack() self.btnopen = tk.Button(self, text=" Child Open Window", command=self.openChildOpenWindow) self.btnopen.pack() # show a label self.ts = time.time() # 放在這裡更新 self.st = datetime.datetime.fromtimestamp(self.ts).strftime('%Y-%m-%d %H:%M:%S') self.label = tk.Label(self, text=self.st) self.label.pack(ipadx=10, ipady=10) self.protocol("WM_DELETE_WINDOW", self.closeWindows) # 關閉視窗時調用closeWindows方法 # create a menubar self.menubar = Menu() self.config(menu=self.menubar) # create the file_menu self.fileMenu = Menu( self.menubar, tearoff=0 ) # add menu items to the File menu self.fileMenu.add_command(label='New', command=self.openChildNewWindow) self.fileMenu.add_command(label='Open...', command=self.openChildOpenWindow) self.fileMenu.add_command(label='Close') self.fileMenu.add_separator() # add a submenu self.subMenu = Menu(self.fileMenu, tearoff=0) self.subMenu.add_command(label='Keyboard Shortcuts') self.subMenu.add_command(label='Color Themes') # add the File menu to the menubar self.fileMenu.add_cascade( label="Preferences", menu=self.subMenu ) # add Exit menu item self.fileMenu.add_separator() self.fileMenu.add_command( label='Exit', command=self.destroy ) self.menubar.add_cascade( label="File", menu=self.fileMenu, underline=0 ) # create the Help menu self.helpMenu = Menu( self.menubar, tearoff=0 ) self.helpMenu.add_command(label='Welcome') self.helpMenu.add_command(label='About...') # add the Help menu to the menubar self.menubar.add_cascade( label="Help", menu=self.helpMenu, underline=0 ) # self.after(1000,goWindows) # self.stateCity = {"江西":"南昌","西藏":"拉薩", # "新疆":"烏魯木齊","寧夏":"銀川", # "江蘇":"南京","山東":"青島", # "廣東":"廣州","福建":"福州","山東":"濟南","安徽":"合肥", # "湖北":"武漢","湖南":"長沙", # "陝西":"西安","貴州":"貴陽", # "四川":"成都","青海":"銀川","甘肅":"蘭州", # "內蒙古":"呼爾浩特","遼寧":"瀋陽", # "吉林":"長春","黑龍江":"哈爾濱","廣西":"南寧", # "雲南":"昆明","山西":"太原","浙江":"杭州", # "台灣":"臺北","河北":"石傢莊","河南":"鄭州","北京":"朝陽", # "上海":"閔行","天津":"濱海","重慶":"解放碑"} self.stuData = [[1, 'geovindu', '0002', '2008-01-03', 16], [2, 'jason', '0001', '2007-02-13', 13], [3, 'ada', '0003', '2008-02-14', 11] , [4, 'link', '0004', '2007-03-14', 10], [5, 'dus', '0005', '2007-02-12', 10], [6, 'bike', '0006', '2007-02-14', 17] , [7, 'eson', '0007', '2007-04-14', 17], [8, 'fok', '0008', '2007-02-11', 17], [9, 'hosrse', '0009', '2006-02-14', 10] , [10, 'ken', '0011', '2007-05-14', 12], [11, 'red', '0021', '2007-02-10', 12], [12, 'mike', '0031', '2005-02-14', 13] , [13, 'nike', '0012', '2007-06-14', 27], [14, 'queen', '0022', '2007-02-24', 15], [15, 'pen', '0023', '2004-02-14', 12] , [16, 'yelu', '0033', '2007-07-14', 22], [17, 'zoon', '0043', '2007-02-23', 14], [18, 'work', '0051', '2003-02-14', 16] , [19, 'ven', '0061', '2007-08-14', 13], [20, 'tesk', '0071', '2007-02-22', 11], [21, 'ilove', '0081', '2002-02-14', 15] , [22, 'open', '0091', '2007-09-14', 14], [23, 'seeek', '0092', '2007-02-21', 18], [24, 'uluko', '0028', '2009-02-14', 19] , [25, 'xero', '0101', '2007-10-14', 11], [26, 'xoo', '0201', '2007-02-20', 16], [27, 'yyeluey', '0301', '2017-02-14', 21] , [28, 'shenzhen', '0401', '2007-12-14', 10], [29, 'guanzhou', '0501', '2007-02-19', 19], [30, 'beiking', '0601', '2014-02-14', 20] , [31, 'qinhua', '0701', '2007-11-14', 16], [32, 'nanchang', '0001', '2007-02-18', 20], [33, 'jian', '0801', '2015-02-14', 14] ] # 建立Treeview self.tree = Treeview(self,style='success.Treeview',height=50,show='headings') #, columns=("StudentId", "StudentName", "StudentNO", "StudentBirthday", "Age") """ 定義捲軸控制項 orient為捲軸的方向,vertical--縱向,horizontal--橫向 command=self.tree.yview 將捲軸綁定到treeview控制項的Y軸 """ '''消除第一行空列''' #self.tree['show'] = 'headings' self.tree.pack() # 1 # self.yscrollbar = Scrollbar(self, orient='vertical', command=self.tree.yview) # self.yscrollbar.place(relx=0.971, rely=0.028, relwidth=0.024, relheight=0.958) # 2 self.yscrollbar = Scrollbar(self) self.yscrollbar.pack(side=RIGHT, fill=Y) self.yscrollbar.config(command=self.tree.yview) self.tree.configure(yscrollcommand=self.yscrollbar.set) self.headtext=['序號','姓名','學號','出生日期','年齡'] # 定義列 self.tree['columns']=("StudentId","StudentName","StudentNO","StudentBirthday","Age") # 設置列屬性,列不顯示 """ self.tree.column("StudentId", width=150, minwidth=100, anchor=S) self.tree.column("StudentName", width=150, minwidth=100, anchor=S) self.tree.column("StudentNO", width=150, minwidth=100, anchor=S) self.tree.column("StudentBirthday", width=150, minwidth=100, anchor=S) self.tree.column("Age", width=150, minwidth=100, anchor=S) # 設置表頭 self.tree.heading("StudentId", text="序號", command=lambda c="StudentId": self.treeviewSortColumn(c)) self.tree.heading("StudentName", text="姓名", command=lambda c="StudentName": self.treeviewSortColumn(c)) self.tree.heading("StudentNO", text="學號", command=lambda c="StudentNO": self.treeviewSortColumn(c)) self.tree.heading("StudentBirthday", text="出生日期", command=lambda c="StudentBirthday": self.treeviewSortColumn(c)) self.tree.heading("Age", text="年齡", command=lambda c="Age": self.treeviewSortColumn(c)) """ k=0 for column in self.tree['column']: self.tree.column(column, width=150, minwidth=100, anchor=S) self.tree.heading(column, text=self.headtext[k], command=lambda c=column: self.treeviewSortColumn(c)) k=k+1 # 建立欄標題 # self.tree.heading("#0",text="StudentId",command=lambda c="StudentId": self.treeviewSortColumn(c)) # 圖示欄位元icon column # self.tree.heading("#1",text="StudentName",command=lambda c="StudentName": self.treeviewSortColumn(c)) # self.tree.heading("#2",text="StudentNO",command=lambda c="StudentNO": self.treeviewSortColumn(c)) # self.tree.heading("#3",text="StudentBirthday",command=lambda c="StudentBirthday": self.treeviewSortColumn(c)) # self.tree.heading("#4",text="Age",command=lambda c="Age": self.treeviewSortColumn(c)) i = 0 # 建立內容 多一個空列 for StudentId, StudentName, StudentNO, StudentBirthday, Age in self.stuData: # self.tree.insert("",index=END,text=state,values=self.stateCity[state]) self.tree.insert("", index=END,text=StudentId,values=(StudentId, StudentName, StudentNO, StudentBirthday, Age)) i = i + 1 self.tree.bind("<Double-1>", self.doubleClick) # 連按2下綁定doubleClick方法 style = Style() style.map("Treeview", foreground=self.fixedMap("foreground"), background=self.fixedMap("background")) #定義背景色風格 self.tree.tag_configure('even', background='lightblue') # even標籤設定為淺藍色背景顏色 self.treeColor() def fixedMap(self,option): """ :return """ style = Style() return [elm for elm in style.map("Treeview", query_opt=option) if elm[:2] != ("!disabled", "!selected")] def treeColor(self): """ 表格欄隔行顯示不同顏色函數 :return """ self.items=self.tree.get_children() # 得到根目錄所有行的iid i=0 # 初值 for hiid in self.items: if i/2!=int(i/2): # 判斷奇偶 tag1='' # 奇數行 else: tag1='even' # 偶數行 self.tree.item(hiid,tag=tag1) # 偶數行設為淺藍色的tag='even' i+=1 # 累加1 def openChildNewWindow(self): """ :return: """ subwindow = ChildNewWindow(self) self.update() # 刷新主窗口 def openChildOpenWindow(self): #data = [35, '塗聚文', '0801', '2015-02-14', 14] try: strtreeitem = self.tree.selection()[0] # iid if strtreeitem is not None: values = self.tree.item(strtreeitem, option='values') # 取值 print(values) data = [values[0], values[1], values[2], values[3], values[4]] subwindow = ChildOpenWindow(self, data) self.update() # 刷新主窗口 else: pass except Exception as ex: showinfo("提示", "請選定一行記錄!") def closeWindows(self): """ close :return """ msgbye() self.destroy() # 關閉 def goWindows(self): """ :return: """ # ChildBack=u32.GetParent(ChildNewWindow(self).winfo_id()) MainBack = u32.GetParent(self.winfo_id()) u32.SetParent(MainBack, self.winfo_id()) # u32.SetParent(ChildBack,self.winfo_id()) def doubleClick(self, event): """ 雙擊事件 StudentId, StudentName, StudentNO, StudentBirthday, Age :param event :return: """ e = event.widget # 取得事件控制項 iid = e.identify("item", event.x, event.y) # 取得連按2下專案id StudentId = e.item(iid, "text") # 取得StudentId StudentName = e.item(iid, "values")[1] # 取得StudentName StudentNO = e.item(iid, "values")[2] StudentBirthday= e.item(iid, "values")[3] Age= e.item(iid, "values")[4] str = "{0} : {1}".format(StudentId, StudentName) # 格式化 data = [StudentId, StudentName,StudentNO,StudentBirthday,Age] # messagebox.showinfo("Double Clicked",str) # 輸出 child = ChildOpenWindow(self, data) self.update() def isNumber(self, tel: str) -> bool: """ 驗證是數字的 :param tel :return """ try: pattern = r'^\d+$' # 匹配8位元數字 {8} if re.match(pattern, tel): # print("電話號碼有效!") return True else: # print("電話號碼無效!") return False except (ValueError, IndexError, EnvironmentError): return False except Exception as ex: print(ex) return False def treeviewSortColumn(self, col): """ 字母可以排序,數字排序,其它類型冇考慮,自己再寫 :param col: 列名 :return: """ global reverseFlag # 定義排序旗標全域變數 可以判斷字元類型進行排序 lst = [(self.tree.set(st, col), st) for st in self.tree.get_children("")] # print(lst) # 列印列表 if type(lst[0]) == int: lst.sort(key=lambda lst: int(lst[0]), reverse=self.reverseFlag) # 排序列表 else: lst.sort(key=lambda lst: lst[0], reverse=self.reverseFlag) print(lst) # 列印列表 newdata = [] for num, ids in lst: if self.isNumber(num): # 考慮字串類型 print(int(num), ids) newdata.append((int(num), ids)) else: print(num, ids) newdata.append((num, ids)) newdata.sort(key=lambda newdata: newdata[0], reverse=self.reverseFlag) for index, item in enumerate(newdata): # 重新移動專案內容 以字元排序 self.tree.move(item[1], "", index) print(index, item[0]) self.reverseFlag = not self.reverseFlag # 更改排序旗標 def __delattr__(self): """ :return: """ print('del1') def __del__(self): """ :return: """ print('del2') # 需要消 def msg(): """ :return: """ showinfo("Notebook", "welcome GeovinDu's Notebook") def msgbye(): """ :return: """ showinfo("ByeBye", "welcome GeovinDu's Notebook,bye!") class ChildNewWindow(tk.Toplevel): """ 子表單 """ def __init__(self, master): """ :param master: """ super().__init__(master) # self._data=data self.title("Child Window") self.geometry('{}x{}'.format(850, 900)) self.label = tk.Label(self, text="Child Window") self.label.pack() self.attributes('-topmost', 'true') # 表單最上層 self.protocol("WM_DELETE_WINDOW", self.closeWindows) # 關閉視窗時調用closeWindows方法 def closeWindows(self): """ close :return """ self.destroy() # 關閉 self.master.destroy() # 關閉主視窗,不關閉,還是原有畫布的資料,不更新資料,如何想一個更好的方法封裝? msg() main = MainWindow() # 重新載入表單 更新表單資料 main.attributes('-topmost', 'true') # 表單最上層 main.mainloop() self.master.update() class ChildOpenWindow(tk.Toplevel): """ 子表單 """ def __init__(self, master, data): """ :param master: :param data: """ super().__init__(master) self.master = master self._data = data self.title("Open Window") self.geometry('{}x{}'.format(850, 900)) self.label = tk.Label(self, text="Open Window, Geovin Du like you.") # self.Toplevel(self.master) self.label.pack() self.attributes('-topmost', 'true') # 表單最上層 self.protocol("WM_DELETE_WINDOW", self.closeWindows) # 關閉視窗時調用closeWindows方法 # StudentId, StudentName, StudentNO, StudentBirthday, Age self.StudentId = tk.Label(self, text=f'id:{self._data[0]}') self.StudentId.pack() self.StudentName = tk.Label(self, text=f'Name:{self._data[1]}') self.StudentName.pack() self.StudentNO = tk.Label(self, text=f'NO:{self._data[2]}') self.StudentNO.pack() self.StudentBirthday = tk.Label(self, text=f'Birthday:{self._data[3]}') self.StudentBirthday.pack() self.Age = tk.Label(self, text=f'Age:{self._data[4]}') self.Age.pack() def closeWindows(self): """ close :return """ self.destroy() # 關閉現窗口 self.master.destroy() # 關閉主視窗 不關閉,還是原有畫布的資料,不更新資料,如何想一個更好的方法封裝? msg() main = MainWindow() # 重新載入表單 更新表單資料 main.attributes('-topmost', 'true') # 表單最上層 main.mainloop() self.master.update() if __name__=="__main__": """ main output """ mainwindow = MainWindow() #mainwindow.after(1000,mainwindow.goWindows()) mainwindow.mainloop()
哲学管理(学)人生, 文学艺术生活, 自动(计算机学)物理(学)工作, 生物(学)化学逆境, 历史(学)测绘(学)时间, 经济(学)数学金钱(理财), 心理(学)医学情绪, 诗词美容情感, 美学建筑(学)家园, 解构建构(分析)整合学习, 智商情商(IQ、EQ)运筹(学)生存.---Geovin Du(涂聚文)