前言
前面用tkinter做了一個巨醜的GUI介面,今天想把它變漂亮起來,重新找回page做了一個介面,它也是基於tkinter開發的所見即所得的介面編輯器,前面因為程式碼搞不明白沒用上,現在重新研究一下。
一、開啟page,軟體自己在網上搜尋下載的。它的介面挺有意思的,不是我們常見的形式,它分開了五個部分可以隨便拖動,各部分間就是桌面,沒有連在一起。
New Toplevel 就是工作臺,可以將元件放置在上面。
Widget Toolbar 裡就是可用的元件。
Attrbute Editor 編輯元件屬性。
Widget Tree 元件導航樹。
page手冊:https://www.kancloud.cn/gnefnuy/python/1316391 (全網只找到這一個,誰還有其它資料的請留言,謝謝)
二、畫好自己的介面,這下漂亮多了。
三、接下來匯出python檔案,這很重要,匯出後就可以直接執行py檔案生成介面。
1、選取選單如截圖
2、在彈出的頁面點選‘save’,將這個GUI檔案儲存到你的project資料夾下。
3、選取選單如截圖
4、同樣在彈出的頁面點選‘save’,將這個檔案儲存到你的project資料夾下。(如果漏了這個檔案,GUI執行就會報錯)
5、現在試執行一下GUI的py檔案。執行正常。
四、GUI做好,接下來要寫邏輯了。
1、mysql的設定上一篇已經做過了,一些邏輯也可以照搬過來,現在主要的問題有兩個。
一是原來的lisbox選擇查詢項改成了Combobox來做,要重新寫程式碼。
二是原來所有東西都寫在一個py上,現在出現了兩個py檔案(UI.py和UI_support.py),邏輯該寫在哪,要研究一下。
2、combobox是從ttk引用的元件,不是tkinter上的,所以要記得import ttk(page生成的py檔案已有)。
兩個檔案研究不出所以,先直接在UI.py上寫Combobox的資料來源。
#從student表表頭載入下拉選單 sql_sr = "SELECT COLUMN_NAME FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = 'test' AND TABLE_NAME = 'student'" cbox_val = sql().select(sql_sr) self.input_name = ttk.Combobox(top) self.input_name.place(relx=0.192, rely=0.067, relheight=0.051 , relwidth=0.172) self.input_name.configure(values = cbox_val) #設定下拉選單的值 self.input_name.configure(state='readonly') #設定為只讀 self.input_name.configure(takefocus="")
下面還有一個插入時的Combobox,程式碼類似。
#載入下拉選單來源 sql_sr2 = "select class.name from class" cbox_val2 = sql().select(sql_sr2) self.insert_class = ttk.Combobox(top) self.insert_class.place(relx=0.6, rely=0.733, relheight=0.051 , relwidth=0.172) self.insert_class.configure(values = cbox_val2) self.insert_class.configure(textvariable=UI_support.combobox) self.insert_class.configure(state='readonly') #設定為只讀 self.insert_class.configure(takefocus="") self.insert_class.configure(cursor="fleur")
結果:
修改:讀了一下page手冊,發現UI.py是儘量不動的(修改介面後再生成程式碼會覆蓋掉修改內容),要寫到UI_support.py,嘗試將下拉選單初始化寫入def init
def init(top, gui, *args, **kwargs): global w, top_level, root w = gui top_level = top root = top sql_sr = "SELECT COLUMN_NAME FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = 'test' AND TABLE_NAME = 'student'" cbox_val = sql().select(sql_sr) w.input_name.configure(values = cbox_val) #設定下拉選單的值 w.input_name.configure(state='readonly') #設定為只讀 sql_sr2 = "select class.name from class" cbox_val2 = sql().select(sql_sr2) w.insert_class.configure(values = cbox_val2) w.insert_class.configure(state='readonly')
執行顯示倒是正常的,但一選擇值就出問題了,兩個下拉選單值同時變了,得再找原因。
CSDN上找到這個說法:
再回頭檢視程式碼,在UI_support.py中作如下修改:
def set_Tk_var(): global combobox combobox = tk.StringVar() global combobox2 #增加一個資料來源給第二個commbox引用 combobox2 = tk.StringVar()
在UI.py中修改第二個commbox元件的資料來源
self.insert_class = ttk.Combobox(top) self.insert_class.place(relx=0.6, rely=0.733, relheight=0.051 , relwidth=0.172) self.insert_class.configure(textvariable=UI_support.combobox2)#修改資料來源 self.insert_class.configure(takefocus="")
執行測試OK,不過存在一個問題就是還是修改了UI.py的程式碼,要是有介面調整,用page再生成程式碼會覆蓋掉修改的地方,估計修改資料來源可以直接從page下手修改,這個放到後面再研究吧。
3、接下來要寫從下拉選單獲取焦點值,以及‘查詢’和‘新增’按鈕的邏輯。目前點選這兩個按鈕發現呼叫的是UI_support.py裡的函式,那麼就應該去UI_support.py裡去寫這兩個按鈕的邏輯了,試試看。
先寫“查詢”按鈕
def on_select(): w.show_list.delete(0,'end') #清空顯示區原有資訊 name = w.input_name.get() #獲取下拉選單當前值 varlue = w.input_valuse.get() sql_sr = "select * from Student where student." + name + "=" + "'" + varlue +"'" result = sql().select(sql_sr) for x in result: w.show_list.insert('end',x) sys.stdout.flush()
查詢成功
再寫“新增”按鈕
def on_insert(): name = w.insert_name.get() age = w.insert_age.get() sex = w.insert_sex.get() myclass = w.insert_class.get() sql_sr = "INSERT INTO Student (name,age,sex,class) VALUES ('"+name+"',"+age+","+sex+",'"+myclass+"')" print(sql_sr) sql().insert(sql_sr) sys.stdout.flush()
執行成功,新增一條記錄
4、至此,這個小工具算是完成了,前後搞了一個多星期,碰到啥問題就去查詢資料,程式設計小白沒辦法,不過做成了還是有些許竊喜的,最後貼上兩個檔案的最終程式碼。
UI.py
1 #! /usr/bin/env python 2 # -*- coding: utf-8 -*- 3 # 4 # GUI module generated by PAGE version 5.4 5 # in conjunction with Tcl version 8.6 6 # Nov 13, 2020 11:21:14 AM CST platform: Windows NT 7 8 import sys 9 10 try: 11 import Tkinter as tk 12 except ImportError: 13 import tkinter as tk 14 15 try: 16 import ttk 17 py3 = False 18 except ImportError: 19 import tkinter.ttk as ttk 20 py3 = True 21 22 import UI_support 23 24 def vp_start_gui(): 25 '''Starting point when module is the main routine.''' 26 global val, w, root 27 root = tk.Tk() 28 UI_support.set_Tk_var() 29 top = database (root) 30 UI_support.init(root, top) 31 root.mainloop() 32 33 w = None 34 def create_database(rt, *args, **kwargs): 35 '''Starting point when module is imported by another module. 36 Correct form of call: 'create_database(root, *args, **kwargs)' .''' 37 global w, w_win, root 38 #rt = root 39 root = rt 40 w = tk.Toplevel (root) 41 UI_support.set_Tk_var() 42 top = database (w) 43 UI_support.init(w, top, *args, **kwargs) 44 return (w, top) 45 46 def destroy_database(): 47 global w 48 w.destroy() 49 w = None 50 51 class database: 52 def __init__(self, top=None): 53 '''This class configures and populates the toplevel window. 54 top is the toplevel containing window.''' 55 _bgcolor = '#d9d9d9' # X11 color: 'gray85' 56 _fgcolor = '#000000' # X11 color: 'black' 57 _compcolor = '#d9d9d9' # X11 color: 'gray85' 58 _ana1color = '#d9d9d9' # X11 color: 'gray85' 59 _ana2color = '#ececec' # Closest X11 color: 'gray92' 60 self.style = ttk.Style() 61 if sys.platform == "win32": 62 self.style.theme_use('winnative') 63 self.style.configure('.',background=_bgcolor) 64 self.style.configure('.',foreground=_fgcolor) 65 self.style.configure('.',font="TkDefaultFont") 66 self.style.map('.',background= 67 [('selected', _compcolor), ('active',_ana2color)]) 68 69 top.geometry("600x450+518+418") 70 top.minsize(120, 1) 71 top.maxsize(1924, 1061) 72 top.resizable(1, 1) 73 top.title("Database") 74 top.configure(background="#ffffff") 75 top.configure(highlightbackground="#d9d9d9") 76 top.configure(highlightcolor="black") 77 78 self.select_button = tk.Button(top) 79 self.select_button.place(relx=0.817, rely=0.06, height=28, width=55) 80 self.select_button.configure(activebackground="#ececec") 81 self.select_button.configure(activeforeground="#000000") 82 self.select_button.configure(background="#d9d9d9") 83 self.select_button.configure(command=UI_support.on_select) 84 self.select_button.configure(disabledforeground="#a3a3a3") 85 self.select_button.configure(foreground="#000000") 86 self.select_button.configure(highlightbackground="#d9d9d9") 87 self.select_button.configure(highlightcolor="black") 88 self.select_button.configure(pady="0") 89 self.select_button.configure(text='''查詢''') 90 91 self.menubar = tk.Menu(top,font="TkMenuFont",bg=_bgcolor,fg=_fgcolor) 92 top.configure(menu = self.menubar) 93 94 self.input_valuse = tk.Entry(top) 95 self.input_valuse.place(relx=0.5, rely=0.067,height=27, relwidth=0.173) 96 self.input_valuse.configure(background="white") 97 self.input_valuse.configure(disabledforeground="#a3a3a3") 98 self.input_valuse.configure(font="TkFixedFont") 99 self.input_valuse.configure(foreground="#000000") 100 self.input_valuse.configure(highlightbackground="#d9d9d9") 101 self.input_valuse.configure(highlightcolor="black") 102 self.input_valuse.configure(insertbackground="black") 103 self.input_valuse.configure(selectbackground="blue") 104 self.input_valuse.configure(selectforeground="white") 105 106 self.Label1 = tk.Label(top) 107 self.Label1.place(relx=0.083, rely=0.067, height=23, width=54) 108 self.Label1.configure(activebackground="#f9f9f9") 109 self.Label1.configure(activeforeground="black") 110 self.Label1.configure(background="#d9d9d9") 111 self.Label1.configure(disabledforeground="#a3a3a3") 112 self.Label1.configure(foreground="#000000") 113 self.Label1.configure(highlightbackground="#d9d9d9") 114 self.Label1.configure(highlightcolor="black") 115 self.Label1.configure(text='''查詢項:''') 116 117 self.Label2 = tk.Label(top) 118 self.Label2.place(relx=0.41, rely=0.067, height=23, width=42) 119 self.Label2.configure(activebackground="#f9f9f9") 120 self.Label2.configure(activeforeground="black") 121 self.Label2.configure(background="#d9d9d9") 122 self.Label2.configure(disabledforeground="#a3a3a3") 123 self.Label2.configure(foreground="#000000") 124 self.Label2.configure(highlightbackground="#d9d9d9") 125 self.Label2.configure(highlightcolor="black") 126 self.Label2.configure(text='''數值:''') 127 128 self.insert_button = tk.Button(top) 129 self.insert_button.place(relx=0.817, rely=0.844, height=28, width=55) 130 self.insert_button.configure(activebackground="#ececec") 131 self.insert_button.configure(activeforeground="#000000") 132 self.insert_button.configure(background="#d9d9d9") 133 self.insert_button.configure(command=UI_support.on_insert) 134 self.insert_button.configure(disabledforeground="#a3a3a3") 135 self.insert_button.configure(foreground="#000000") 136 self.insert_button.configure(highlightbackground="#d9d9d9") 137 self.insert_button.configure(highlightcolor="black") 138 self.insert_button.configure(pady="0") 139 self.insert_button.configure(text='''新增''') 140 141 self.input_name = ttk.Combobox(top) 142 self.input_name.place(relx=0.183, rely=0.067, relheight=0.051 143 , relwidth=0.172) 144 self.input_name.configure(textvariable=UI_support.combobox) 145 self.input_name.configure(takefocus="") 146 self.input_name.configure(cursor="X_cursor") 147 148 self.Label1_2 = tk.Label(top) 149 self.Label1_2.place(relx=0.083, rely=0.156, height=23, width=42) 150 self.Label1_2.configure(activebackground="#f9f9f9") 151 self.Label1_2.configure(activeforeground="black") 152 self.Label1_2.configure(background="#d9d9d9") 153 self.Label1_2.configure(disabledforeground="#a3a3a3") 154 self.Label1_2.configure(foreground="#000000") 155 self.Label1_2.configure(highlightbackground="#d9d9d9") 156 self.Label1_2.configure(highlightcolor="black") 157 self.Label1_2.configure(text='''結果:''') 158 159 self.show_list = tk.Listbox(top) 160 self.show_list.place(relx=0.083, rely=0.2, relheight=0.267 161 , relwidth=0.823) 162 self.show_list.configure(background="white") 163 self.show_list.configure(disabledforeground="#a3a3a3") 164 self.show_list.configure(font="TkFixedFont") 165 self.show_list.configure(foreground="#000000") 166 self.show_list.configure(highlightbackground="#d9d9d9") 167 self.show_list.configure(highlightcolor="black") 168 self.show_list.configure(selectbackground="blue") 169 self.show_list.configure(selectforeground="white") 170 171 self.Label1_3 = tk.Label(top) 172 self.Label1_3.place(relx=0.09, rely=0.518, height=23, width=64) 173 self.Label1_3.configure(activebackground="#f9f9f9") 174 self.Label1_3.configure(activeforeground="black") 175 self.Label1_3.configure(background="#d9d9d9") 176 self.Label1_3.configure(disabledforeground="#a3a3a3") 177 self.Label1_3.configure(foreground="#000000") 178 self.Label1_3.configure(highlightbackground="#d9d9d9") 179 self.Label1_3.configure(highlightcolor="black") 180 self.Label1_3.configure(text='''新增資料:''') 181 182 self.Label1_4 = tk.Label(top) 183 self.Label1_4.place(relx=0.1, rely=0.622, height=23, width=54) 184 self.Label1_4.configure(activebackground="#f9f9f9") 185 self.Label1_4.configure(activeforeground="black") 186 self.Label1_4.configure(background="#d9d9d9") 187 self.Label1_4.configure(disabledforeground="#a3a3a3") 188 self.Label1_4.configure(foreground="#000000") 189 self.Label1_4.configure(highlightbackground="#d9d9d9") 190 self.Label1_4.configure(highlightcolor="black") 191 self.Label1_4.configure(text='''姓名:''') 192 193 self.Label1_5 = tk.Label(top) 194 self.Label1_5.place(relx=0.467, rely=0.622, height=23, width=54) 195 self.Label1_5.configure(activebackground="#f9f9f9") 196 self.Label1_5.configure(activeforeground="black") 197 self.Label1_5.configure(background="#d9d9d9") 198 self.Label1_5.configure(disabledforeground="#a3a3a3") 199 self.Label1_5.configure(foreground="#000000") 200 self.Label1_5.configure(highlightbackground="#d9d9d9") 201 self.Label1_5.configure(highlightcolor="black") 202 self.Label1_5.configure(text='''年齡:''') 203 204 self.Label1_6 = tk.Label(top) 205 self.Label1_6.place(relx=0.1, rely=0.733, height=23, width=54) 206 self.Label1_6.configure(activebackground="#f9f9f9") 207 self.Label1_6.configure(activeforeground="black") 208 self.Label1_6.configure(background="#d9d9d9") 209 self.Label1_6.configure(disabledforeground="#a3a3a3") 210 self.Label1_6.configure(foreground="#000000") 211 self.Label1_6.configure(highlightbackground="#d9d9d9") 212 self.Label1_6.configure(highlightcolor="black") 213 self.Label1_6.configure(text='''性別:''') 214 215 self.Label1_7 = tk.Label(top) 216 self.Label1_7.place(relx=0.467, rely=0.738, height=23, width=54) 217 self.Label1_7.configure(activebackground="#f9f9f9") 218 self.Label1_7.configure(activeforeground="black") 219 self.Label1_7.configure(background="#d9d9d9") 220 self.Label1_7.configure(disabledforeground="#a3a3a3") 221 self.Label1_7.configure(foreground="#000000") 222 self.Label1_7.configure(highlightbackground="#d9d9d9") 223 self.Label1_7.configure(highlightcolor="black") 224 self.Label1_7.configure(text='''班級:''') 225 226 self.insert_name = tk.Entry(top) 227 self.insert_name.place(relx=0.233, rely=0.622, height=27, relwidth=0.173) 228 229 self.insert_name.configure(background="white") 230 self.insert_name.configure(disabledforeground="#a3a3a3") 231 self.insert_name.configure(font="TkFixedFont") 232 self.insert_name.configure(foreground="#000000") 233 self.insert_name.configure(highlightbackground="#d9d9d9") 234 self.insert_name.configure(highlightcolor="black") 235 self.insert_name.configure(insertbackground="black") 236 self.insert_name.configure(selectbackground="blue") 237 self.insert_name.configure(selectforeground="white") 238 239 self.insert_age = tk.Entry(top) 240 self.insert_age.place(relx=0.6, rely=0.622,height=27, relwidth=0.173) 241 self.insert_age.configure(background="white") 242 self.insert_age.configure(disabledforeground="#a3a3a3") 243 self.insert_age.configure(font="TkFixedFont") 244 self.insert_age.configure(foreground="#000000") 245 self.insert_age.configure(highlightbackground="#d9d9d9") 246 self.insert_age.configure(highlightcolor="black") 247 self.insert_age.configure(insertbackground="black") 248 self.insert_age.configure(selectbackground="blue") 249 self.insert_age.configure(selectforeground="white") 250 251 self.insert_sex = tk.Entry(top) 252 self.insert_sex.place(relx=0.233, rely=0.733,height=27, relwidth=0.173) 253 self.insert_sex.configure(background="white") 254 self.insert_sex.configure(disabledforeground="#a3a3a3") 255 self.insert_sex.configure(font="TkFixedFont") 256 self.insert_sex.configure(foreground="#000000") 257 self.insert_sex.configure(highlightbackground="#d9d9d9") 258 self.insert_sex.configure(highlightcolor="black") 259 self.insert_sex.configure(insertbackground="black") 260 self.insert_sex.configure(selectbackground="blue") 261 self.insert_sex.configure(selectforeground="white") 262 263 self.insert_class = ttk.Combobox(top) 264 self.insert_class.place(relx=0.6, rely=0.733, relheight=0.051 265 , relwidth=0.172) 266 self.insert_class.configure(textvariable=UI_support.combobox2)#修改資料來源 267 self.insert_class.configure(takefocus="") 268 269 if __name__ == '__main__': 270 vp_start_gui()
UI_support.py
1 #! /usr/bin/env python 2 # -*- coding: utf-8 -*- 3 # 4 # Support module generated by PAGE version 5.4 5 # in conjunction with Tcl version 8.6 6 # Oct 20, 2020 09:35:42 AM CST platform: Windows NT 7 # Nov 03, 2020 05:18:17 PM CST platform: Windows NT 8 # Nov 03, 2020 05:19:47 PM CST platform: Windows NT 9 10 import sys 11 12 try: 13 import Tkinter as tk 14 except ImportError: 15 import tkinter as tk 16 17 try: 18 import ttk 19 py3 = False 20 except ImportError: 21 import tkinter.ttk as ttk 22 py3 = True 23 24 import mysql.connector 25 class sql: 26 def __init__(self): 27 self.con = mysql.connector.connect( 28 host="localhost", # 資料庫主機地址 29 user="root", # 資料庫使用者名稱 30 passwd="123456", # 資料庫密碼 31 database="test" #資料庫名稱 32 ) 33 self.cursor = self.con.cursor() 34 35 def select(self,sql_sr): #類定義了init後下面的函式第一引數必須是self否則引用報錯 36 self.cursor.execute(sql_sr) 37 result = self.cursor.fetchall() 38 return result 39 40 def insert(self,sql_sr): 41 self.cursor.execute(sql_sr) 42 self.con.commit() 43 print(self.cursor.rowcunt,'新增成功') 44 45 def set_Tk_var(): 46 global combobox 47 combobox = tk.StringVar() 48 global combobox2 #增加一個資料來源給第二個commbox引用 49 combobox2 = tk.StringVar() 50 global selectedButton 51 selectedButton = tk.IntVar() 52 53 def init(top, gui, *args, **kwargs): 54 global w, top_level, root 55 w = gui 56 top_level = top 57 root = top 58 59 sql_sr = "SELECT COLUMN_NAME FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = 'test' AND TABLE_NAME = 'student'" 60 cbox_val = sql().select(sql_sr) 61 w.input_name.configure(values = cbox_val) #設定下拉選單的值,前面定義w是引用UI.py的意思 62 w.input_name.configure(state='readonly') #設定為只讀 63 64 sql_sr2 = "select class.name from class" 65 cbox_val2 = sql().select(sql_sr2) 66 67 w.insert_class.configure(values = cbox_val2) 68 w.insert_class.configure(state='readonly') 69 70 def on_select(): 71 w.show_list.delete(0,'end') #清空顯示區原有資訊 72 name = w.input_name.get() #獲取下拉選單當前值 73 varlue = w.input_valuse.get() 74 sql_sr = "select * from Student where student." + name + "=" + "'" + varlue +"'" 75 result = sql().select(sql_sr) 76 for x in result: 77 w.show_list.insert('end',x) 78 sys.stdout.flush() 79 80 def on_insert(): 81 name = w.insert_name.get() 82 age = w.insert_age.get() 83 sex = w.insert_sex.get() 84 myclass = w.insert_class.get() 85 sql_sr = "INSERT INTO Student (name,age,sex,class) VALUES ('"+name+"',"+age+","+sex+",'"+myclass+"')" 86 print(sql_sr) 87 sql().insert(sql_sr) 88 sys.stdout.flush() 89 90 def destroy_window(): 91 # Function which closes the window. 92 global top_level 93 top_level.destroy() 94 top_level = None 95 96 if __name__ == '__main__': 97 import UI 98 UI.vp_start_gui()