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("", 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()
輸出: