學習編程離不開存取數據,然後在視覺上表現出來,這就涉及到GUI與數據庫的操作。對於大多數的數據庫而言,都要單獨安裝運行,然後在程序中建立連接存取數據。不過初學者練手的話,先從簡單的開始應該是個不錯的選擇。
SQLite是一款輕量型的SQL數據庫,Python自帶,不用單獨安裝,今天俺就學學用PyQt5的GUI操作SQLite數據庫。
目標:建立一個wallet數據庫,包含income、cost、member三個表,可以由三個無線單選按鈕選定在QTableWidget控件中顯示,每個表只有一列數據subject,然後由增加、刪除、修改三個功能按鈕對數據操作並保存在數據庫中。
步驟一、先搭圖形框架
這個在前一篇頭條文章中已經練習過,直接拿來就行。
<code> import sys from PyQt5.QtCore import * from PyQt5.QtWidgets import *class
Table
(QWidget
):
def
__init__
(
self
,parent=None):super
(Table,self
).__init__
(parent)self
.setGeometry(100
,100
,160
,260
)self
.setGUI()def
setGUI
(
self
):self
.setradioG = QButtonGroup()self
.setradio1 = QRadioButton('收入'
)self
.setradio2 = QRadioButton('支出'
)self
.setradio3 = QRadioButton('成員'
)self
.setradio1.setChecked(True)self
.setradioG.addButton(self
.setradio1,0
)self
.setradioG.addButton(self
.setradio2,1
)self
.setradioG.addButton(self
.setradio3,2
)self
.layout41 = QHBoxLayout()self
.layout41.addStretch()self
.layout41.addWidget(self
.setradio1)self
.layout41.addWidget(self
.setradio2)self
.layout41.addWidget(self
.setradio3)self
.layout41.addStretch()self
.tb2 = QTableWidget(5
,1
)self
.tb2.setStyleSheet('background-color:LightSeaGreen;color:white;'
)self
.tb2.verticalHeader().setStyleSheet('background-color:white;color:LightSeaGreen;'
)self
.tb2.horizontalHeader().setStretchLastSection(True)self
.tb2.horizontalHeader().setVisible(False)self
.tb2.setSelectionBehavior(QAbstractItemView.SelectRows)self
.setbtSave=QPushButton('修改'
)self
.setbtIns=QPushButton('增加'
)self
.setbtDel=QPushButton('刪除'
)self
.setbtSave.clicked.connect(self
.on_editButton_clicked)self
.setbtIns.clicked.connect(self
.on_insButton_clicked)self
.setbtDel.clicked.connect(self
.on_delButton_clicked)self
.layout43=QHBoxLayout()self
.layout43.addWidget(self
.setbtIns)self
.layout43.addWidget(self
.setbtDel)self
.layout43.addWidget(self
.setbtSave)self
.layout4 = QVBoxLayout()self
.layout4.addLayout(self
.layout41)self
.layout4.addWidget(self
.tb2)self
.layout4.addStretch()self
.layout4.addLayout(self
.layout43)self
.layout4.setContentsMargins(0
,0
,0
,0
)self
.setLayout(self
.layout4)self
.setWindowFlags(Qt.FramelessWindowHint)if
__name__
=='__main__'
: app=QApplication(sys.argv) table=Table() table.show() sys.exit(app.exec_
())/<code>
上面的代碼運行後就會顯示圖形界面,不過按鈕還沒生效。
步驟二、編寫表格顯示模塊,涉及從數據庫中取出數據,插入到表格控件中,如果表格不存在,會先建立庫表。下面的模塊都插入到上面的主程序中。
<code>def
initTable
(
self
):self
.tableName=['income'
,'cost'
,'member'
] data_list =self
.getData(self
.tableName[self
.setradioG.checkedId()])self
.tb2.setRowCount(len(data_list))for
indexin
range(len(data_list)):self
.tb2.setItem(index,0
, TableWidgetItem(str(data_list[index][0
])))/<code>
其中self.getData()是從數據庫取數據的模塊,代碼如下:
<code>def getData(name): conn = sqlite3.connect('wallet.db') curs = conn.cursor() command = "CREATE
TABLE
IF
NOT
EXISTS
%s (subjectTEXT
PRIMARYKEY
NOT
NULL
);"%(name) c = curs.execute(command) command ='select ROWID,subject from %s'
%(name
) c = curs.execute(command) data_list = []for
row
in
c : temp_list = [] temp_list.append(row
[1
]) data_list.append(temp_list) conn.close()return
data_list/<code>
這段代碼需要導入SQLite數據庫包了:
<code>import
sqlite3/<code>
這段代碼會與數據庫wallet建立連接,如果數據庫不存在,會自動建立。下面的SQL語句會判斷由name傳遞的表名是否存在,不存在會建立相應的income、cost、member表。
'select ROWID,subject from %s'%(name) 從對應的數據表中取出行號和字段內容,將字段內容賦給列表data_list[]傳回給initTable模塊,放在表格控件中顯示。第一次運行由於數據庫中沒有內容,表格也沒有數據顯示。注意:這裡的ROWID是數據表中隱含的,不是我們設定的字段,subject是我們建立的字段。取出ROWID在刪除、修改字段內容時會用到。
還有一點需要注意的是SQL語句中的參數傳遞,直接用?佔位符很多時候會出問題,特別是數據表名稱的傳遞,絕對不能用?佔位符,改用上面的%s進行字符串代換組成SQL命令後再執行就沒問題了。
步驟三、給數據表字段增加內容
"增加"按鈕是與on_insButton_clicked模塊綁定的,因為與"修改"按鈕公用一個界面,所以指向同一個模塊。
<code>def showDialog(self
, status, subject=''
):self
.dialog = QDialog(self
)if
status ==1
:self
.dialog.setWindowTitle('新增'
)else
:self
.dialog.setWindowTitle('修改'
) group = QGroupBox(self
.dialog) lb1 = QLabel('名稱:'
, group)self
.enter = QLineEdit(group) ok_button = QPushButton('確定'
,self
.dialog) cancel_button = QPushButton('取消'
,self
.dialog) group_layout = QVBoxLayout() group_item = [lb1,self
.enter]for
item in group_item: group_layout.addWidget(item) group.setLayout(group_layout) group.setFixedSize(group.sizeHint()) button_layout = QHBoxLayout() button_layout.addWidget(ok_button) button_layout.addWidget(cancel_button) dialog_layout = QVBoxLayout() dialog_layout.addWidget(group) dialog_layout.addLayout(button_layout)self
.dialog.setLayout(dialog_layout)if
status ==1
: ok_button.clicked.connect(self
.addAccept)else
: ok_button.clicked.connect(self
.editAccept) ok_button.setDefault(True
) cancel_button.clicked.connect(self
.dialog.reject)self
.dialog.exec_()return
False
/<code>
裡面涉及下面兩個模塊:
<code>def
addAccept
(
self
):if
self
.enter.text() !=''
:self
.dialog.close()self
.addData(self
.tableName[self
.setradioG.checkedId()],self
.enter.text())self
.initTable()self
.showMsg('新增成功'
)else:
self
.showMsg('不能為空'
)/<code>
<code>def
showMsg
(
self
, message): hint_msg = QMessageBox.about(self
,'提示'
,message)/<code>
我這裡所有數據表都是隻有一個字段,因為是練習做的,所以簡單為上,涉及多個字段的話直接加上就行。
今天先做到這裡,還有刪除模塊下次再加上。