1. 程式人生 > >python實戰GUI介面+mysql

python實戰GUI介面+mysql

前言

前面用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()

&n