0

下面是示例代码:

import sys
from PyQt5 import QtCore, QtWidgets, QtSql, uic


class FilterProxyModel(QtCore.QSortFilterProxyModel):
    def __init__(self, parent=None):
        super().__init__(parent)
        self._filter_value = None

    @property
    def filter_value(self):
        return self._filter_value

    @filter_value.setter
    def filter_value(self, value):
        self._filter_value = value
        self.invalidateFilter()

    def filterAcceptsRow(self, sourceRow, sourceParent):
        if self.filter_value is None:
            return super().filterAcceptsRow(sourceRow, sourceParent)
        if self.filterKeyColumn() >= 0:
            value = (
                self.sourceModel()
                .index(sourceRow, self.filterKeyColumn(), sourceParent)
                .data(self.filterRole())
            )
            return value == self.filter_value

        for column in range(self.columnCount()):
            value = (
                self.sourceModel()
                .index(sourceRow, column, sourceParent)
                .data(self.filterRole())
            )
            if value == self.filter_value:
                return True
        return False

    def setFilterRegExp(self, filter):
        self.filter_value = None
        super().setFilterRegExp(filter)


class UI(QtWidgets.QMainWindow):
    def __init__(self):
        super(UI, self).__init__()
        uic.loadUi("tableview.ui", self)
        self.tableView.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)

        db = QtSql.QSqlDatabase.addDatabase("QSQLITE")
        db.setDatabaseName("book.db")
        db.open()

        self.model = QtSql.QSqlTableModel(self)
        self.model.setTable("card")
        self.model.select()

        self.proxy = FilterProxyModel(self)
        self.proxy.setSourceModel(self.model)

        self.tableView.setModel(self.proxy)
        self.model.select()

        self.edit.clicked.connect(self.edit_items)
        self.refresh.clicked.connect(self.refresh_table)

        r = self.model.record()
        column_names = [r.field(i).name().title() for i in range(r.count())]

        self.comboBox.addItems([x for x in column_names])

        self.horizontalHeader = self.tableView.horizontalHeader()
        self.horizontalHeader.sectionClicked.connect(
            self.tableView_horizontalHeader_sectionClicked
            )
        self.lineEdit.textChanged.connect(self.lineEdit_textChanged)

    def tableView_horizontalHeader_sectionClicked(self, logicalIndex):
        menu = QtWidgets.QMenu(self)

        values = []

        for row in range(self.model.rowCount()):
            value = self.model.index(row, logicalIndex).data(self.proxy.filterRole())
            values.append(value)

        action_all = QtWidgets.QAction("All", self)
        action_all.setData(None)
        menu.addAction(action_all)
        menu.addSeparator()

        for value in sorted(list(set(values))):
            action = QtWidgets.QAction(str(value), self)
            action.setData(value)
            menu.addAction(action)

        headerPos = self.tableView.mapToGlobal(self.horizontalHeader.pos())
        posY = headerPos.y() + self.horizontalHeader.height()
        posX = headerPos.x() + self.horizontalHeader.sectionPosition(logicalIndex)

        action = menu.exec_(QtCore.QPoint(posX, posY))

        if action is not None:
            self.proxy.setFilterKeyColumn(logicalIndex)
            self.proxy.filter_value = action.data()

    def lineEdit_textChanged(self):
        search = QtCore.QRegExp(
            self.lineEdit.text(), QtCore.Qt.CaseInsensitive, QtCore.QRegExp.RegExp
        )
        self.proxy.setFilterKeyColumn(self.comboBox.currentIndex())
        self.proxy.setFilterRegExp(search)

    def edit_items(self):

        if not self.model.rowCount():
            return
        index = self.tableView.currentIndex()
        if index.isValid():
            row = index.row()
        else:
            row = 0

        name_line = QtWidgets.QLineEdit(readOnly=True)
        age_edit = QtWidgets.QSpinBox()
        gender_combo = QtWidgets.QComboBox()
        genders = "M", "F"
        gender_combo.addItems(genders)

        date_of_birth = QtWidgets.QDateEdit()
        date_of_birth.setDisplayFormat("d-MMM-yyyy")
        
        updateButton = QtWidgets.QPushButton("Update")

        mapper = QtWidgets.QDataWidgetMapper()
        mapper.setSubmitPolicy(QtWidgets.QDataWidgetMapper.ManualSubmit)
        mapper.setModel(self.tableView.model())
        mapper.addMapping(name_line, 0)
        mapper.addMapping(age_edit, 1)
        mapper.addMapping(gender_combo, 2)
        mapper.addMapping(date_of_birth, 3)
        
        mapper.setCurrentIndex(row)

        dialog = QtWidgets.QDialog()
        dialog.setWindowTitle("Edit Window")

        layout = QtWidgets.QVBoxLayout(dialog)

        formLayout = QtWidgets.QFormLayout()
        layout.addLayout(formLayout)
        formLayout.addRow("Name", name_line)
        formLayout.addRow("Age", age_edit)
        formLayout.addRow("Gender", gender_combo)
        formLayout.addRow("Date of Birth", date_of_birth)
        
        layout.addWidget(updateButton)
        updateButton.clicked.connect(dialog.accept)

        if dialog.exec_():
            mapper.submit()

    def refresh_table(self):
        print("refresh")


def main():
    app = QtWidgets.QApplication(sys.argv)
    w = UI()
    w.show()
    sys.exit(app.exec_())


if __name__ == "__main__":
    main()

我正在尝试使用 QDataWidgetMapper() 从 Qsqltablemodel 编辑行数据。我的数据库表中的日期列是文本格式,我想使用日期格式作为“d-MMM-yyyy”。当我尝试编辑该行时,日期列将默认日期格式设置为“1-1-2000”。这个怎么做?下面是示例图像: 在此处输入图像描述

4

1 回答 1

1

默认情况下,QtSql 可以处理具有特定格式的字符串列,例如 QDate 和 QDateTime(如sqlite 文档中所示),但在这种情况下,它不符合这些格式,因此 Qt 不知道如何解释它们并将它们显示为文本. 因此,您必须使用委托将该文本转换为 QDate,反之亦然:

class ItemDelegate(QtWidgets.QItemDelegate):
    def setEditorData(self, editor, index):
        if index.column() == 3 and isinstance(editor, QtWidgets.QDateEdit):
            text = index.data()
            date = QtCore.QDate.fromString(text, "d-MMM-yyyy")
            editor.setDate(date)
            return
        super().setEditorData(editor, index)

    def setModelData(self, editor, model, index):
        if index.column() == 3 and isinstance(editor, QtWidgets.QDateEdit):
            text = editor.date().toString("d-MMM-yyyy")
            model.setData(index, text)
            return
        super().setModelData(editor, model, index)
# ...
mapper = QtWidgets.QDataWidgetMapper()
delegate = ItemDelegate(mapper)
mapper.setItemDelegate(delegate)
# ...
于 2020-08-23T14:42:23.103 回答