PyQt5編程(46)—使用數(shù)據(jù)庫(12)

5. QDataWidgetMapper類
QDataWidgetMapper類提供了數(shù)據(jù)模型部分?jǐn)?shù)據(jù)與部件之間的映射。
可以使用QDataWidgetMapper創(chuàng)建與模型某項(xiàng)數(shù)據(jù)關(guān)聯(lián)的感知組件。 如果方向是水平的(默認(rèn)),則數(shù)據(jù)是模型的列數(shù)據(jù),否則是行數(shù)據(jù)。
當(dāng)前索引改變時(shí),每個(gè)關(guān)聯(lián)組件會(huì)被來自模型的數(shù)據(jù)更新。 如果用戶編輯了組件的內(nèi)容,這些更改也會(huì)寫回模型中。 使用addMapping()實(shí)現(xiàn)組件和模型數(shù)據(jù)之間的映射。

addMapping(QWidget widget, int section)
addMapping(QWidget widget, int section, QByteArray propertyName),Qt 4.3中增加的,允許指定傳輸數(shù)據(jù)的屬性(propertyName)。

下列代碼是以phonelog.db數(shù)據(jù)庫,使用該類的示例:

import os
import sys
from PyQt5.QtCore import (QDate, QDateTime, QFile, QVariant, Qt)
from PyQt5.QtWidgets import (QApplication, QDataWidgetMapper,QComboBox,
QDateTimeEdit, QDialog, QGridLayout, QHBoxLayout, QLabel,
QLineEdit, QMessageBox, QPushButton, QVBoxLayout)
from PyQt5.QtSql import (QSqlDatabase, QSqlQuery, QSqlRelation,
QSqlRelationalDelegate, QSqlRelationalTableModel)

DATETIME_FORMAT = "yyyy-MM-dd hh:mm"

class PhoneLogDlg(QDialog):

FIRST, PREV, NEXT, LAST = range(4)

def __init__(self, parent=None):
    super(PhoneLogDlg, self).__init__(parent)

    callerLabel = QLabel("&Caller:")
    self.callerEdit = QLineEdit()
    callerLabel.setBuddy(self.callerEdit)
    today = QDate.currentDate()
    startLabel = QLabel("&Start:")
    self.startDateTime = QDateTimeEdit()
    startLabel.setBuddy(self.startDateTime)
    self.startDateTime.setDateRange(today, today)
    self.startDateTime.setDisplayFormat(DATETIME_FORMAT)
    endLabel = QLabel("&End:")
    self.endDateTime = QDateTimeEdit()
    endLabel.setBuddy(self.endDateTime)
    self.endDateTime.setDateRange(today, today)
    self.endDateTime.setDisplayFormat(DATETIME_FORMAT)
    topicLabel = QLabel("&Topic:")
    topicEdit = QLineEdit()
    topicLabel.setBuddy(topicEdit)
    outcomeLabel = QLabel("&Outcome:")
    self.outcomeComboBox = QComboBox()
    outcomeLabel.setBuddy(self.outcomeComboBox)
    firstButton = QPushButton("第一條")
    prevButton = QPushButton("前一條")
    nextButton = QPushButton("后一條")
    lastButton = QPushButton("最后一條")
    adon = QPushButton("&Add")
    deleteButton = QPushButton("&Delete")
    quitButton = QPushButton("&Quit")
    adon.setFocusPolicy(Qt.NoFocus)
    deleteButton.setFocusPolicy(Qt.NoFocus)

    fieldLayout = QGridLayout()
    fieldLayout.addWidget(callerLabel, 0, 0)
    fieldLayout.addWidget(self.callerEdit, 0, 1, 1, 3)
    fieldLayout.addWidget(startLabel, 1, 0)
    fieldLayout.addWidget(self.startDateTime, 1, 1)
    fieldLayout.addWidget(endLabel, 1, 2)
    fieldLayout.addWidget(self.endDateTime, 1, 3)
    fieldLayout.addWidget(topicLabel, 2, 0)
    fieldLayout.addWidget(topicEdit, 2, 1, 1, 3)
    fieldLayout.addWidget(outcomeLabel, 3, 0)
    fieldLayout.addWidget(self.outcomeComboBox, 3, 1, 1, 3)
    navigationLayout = QHBoxLayout()
    navigationLayout.addWidget(firstButton)
    navigationLayout.addWidget(prevButton)
    navigationLayout.addWidget(nextButton)
    navigationLayout.addWidget(lastButton)
    fieldLayout.addLayout(navigationLayout, 4, 0, 1, 2)
    buttonLayout = QVBoxLayout()
    buttonLayout.addWidget(adon)
    buttonLayout.addWidget(deleteButton)
    buttonLayout.addStretch()
    buttonLayout.addWidget(quitButton)
    layout = QHBoxLayout()
    layout.addLayout(fieldLayout)
    layout.addLayout(buttonLayout)
    self.setLayout(layout)

    self.model = QSqlRelationalTableModel(self)
    self.model.setTable("calls")
    self.model.setRelation(5,
            QSqlRelation("outcomes", "id", "name"))
    self.model.setSort(2, Qt.AscendingOrder)
    self.model.select()

    self.mapper = QDataWidgetMapper(self)
    self.mapper.setSubmitPolicy(QDataWidgetMapper.ManualSubmit)
    self.mapper.setModel(self.model)
    self.mapper.setItemDelegate(QSqlRelationalDelegate(self))
    self.mapper.addMapping(self.callerEdit, 1)
    self.mapper.addMapping(self.startDateTime, 2)
    self.mapper.addMapping(self.endDateTime, 3)
    self.mapper.addMapping(topicEdit, 4)
    relationModel = self.model.relationModel(5)
    self.outcomeComboBox.setModel(relationModel)
    self.outcomeComboBox.setModelColumn(relationModel.fieldIndex("name"))
    self.mapper.addMapping(self.outcomeComboBox, 5)
    self.mapper.toFirst()

    firstButton.clicked.connect(lambda: self.saveRecord(PhoneLogDlg.FIRST))
    prevButton.clicked.connect(lambda: self.saveRecord(PhoneLogDlg.PREV))
    nextButton.clicked.connect(lambda: self.saveRecord(PhoneLogDlg.NEXT))
    lastButton.clicked.connect(lambda: self.saveRecord(PhoneLogDlg.LAST))        
    adon.clicked.connect(self.addRecord)
    deleteButton.clicked.connect(self.deleteRecord)        
    quitButton.clicked.connect(self.done)
    self.setWindowTitle("Phone Log")


def done(self, result=None):
    self.mapper.submit()
    QDialog.done(self, True)


def addRecord(self):
    row = self.model.rowCount()
    self.mapper.submit()
    self.model.insertRow(row)
    self.mapper.setCurrentIndex(row)
    now = QDateTime.currentDateTime()
    self.startDateTime.setDateTime(now)
    self.endDateTime.setDateTime(now)
    self.outcomeComboBox.setCurrentIndex(
            self.outcomeComboBox.findText("Unresolved"))
    self.callerEdit.setFocus()


def deleteRecord(self):
    caller = self.callerEdit.text()
    starttime = self.startDateTime.dateTime().toString(
                                        DATETIME_FORMAT)
    if (QMessageBox.question(self,
            "Delete",
            "Delete call made by

{0} on {1}?".format(caller,starttime),
QMessageBox.Yes|QMessageBox.No) ==
QMessageBox.No):
return
row = self.mapper.currentIndex()
self.model.removeRow(row)
self.model.submitAll()
self.model.select()
if row + 1 >= self.model.rowCount():
row = self.model.rowCount() - 1
self.mapper.setCurrentIndex(row)

def saveRecord(self, where):
    row = self.mapper.currentIndex()
    self.mapper.submit()
    if where == PhoneLogDlg.FIRST:
        row = 0
    elif where == PhoneLogDlg.PREV:
        row = 0 if row <= 1 else row - 1
    elif where == PhoneLogDlg.NEXT:
        row += 1
        if row >= self.model.rowCount():
            row = self.model.rowCount() - 1
    elif where == PhoneLogDlg.LAST:
        row = self.model.rowCount() - 1
    self.mapper.setCurrentIndex(row)

def main():
app = QApplication(sys.argv)

filename = os.path.join(os.path.dirname(__file__), "phonelog.db")
db = QSqlDatabase.addDatabase("QSQLITE")
db.setDatabaseName(filename)
if not db.open():
    QMessageBox.warning(None, "Phone Log",
        QString("Database Error: %1").arg(db.lastError().text()))
    sys.exit(1)

form = PhoneLogDlg()
form.show()
sys.exit(app.exec_())

main()

運(yùn)行結(jié)果:

圖片.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容