QLineEdit为QStyledItemDelegate的QTableView

2024-06-28 14:47:30 发布

您现在位置:Python中文网/ 问答频道 /正文

我希望在QTableView列中有一个“特殊”QlineEdit

  1. 选择Qlinedit时,应选择整个文本(即有效)

  2. 数据应仅在返回键时提交

  3. 转义时,更改应还原为最后一个数据

  4. 仅当数据格式正确时,才应提交(在模型中设置)(参见功能检查数据)

这看起来并不复杂,但我无法让它工作。这里有一个粗略的例子(基于With PySide2 and QTableView how do i get multiple delegates in table view using pandas model?

`

from PySide2 import QtWidgets

from PySide2.QtCore import (Qt, QAbstractTableModel, QModelIndex, QEvent, 
                            
                            QSortFilterProxyModel,
                            QTimer, Slot)
from PySide2.QtWidgets import QAbstractItemDelegate, QTableView, QAbstractItemView, QComboBox, QItemDelegate


class ScheduleModel(QAbstractTableModel):

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

        if schedules_list is None:
            self.schedules_list = []
        else:
            self.schedules_list = schedules_list

    def rowCount(self, index=QModelIndex()):
        return len(self.schedules_list)

    def columnCount(self, index=QModelIndex()):
        return 3

    def data(self, index, role=Qt.DisplayRole):
        col = index.column()
        if index.isValid():
            if role in [Qt.DisplayRole, Qt.EditRole]:
                value = self.schedules_list[index.row()][index.column()]
                return str(value)
        return None

    def headerData(self, section, orientation, role):
        # section is the index of the column/row.
        if orientation == Qt.Horizontal and role == Qt.DisplayRole:
            return ["A", "B", "edit"][section]
        if orientation == Qt.Vertical and role == Qt.DisplayRole:
            return str(section)


    def setData(self, index, value, role=Qt.EditRole):
        if role != Qt.EditRole:
            return False

        if index.isValid() and 0 <= index.row() < len(self.schedules_list):
            self.schedules_list[index.row()][index.column()] = value
            print("data set")
            if self.data(index, Qt.DisplayRole) == value:
                self.dataChanged.emit(index, index, (Qt.EditRole,))
                return True
        return False

    def flags(self, index):
        if 1 <= index.column() <= 5:
            return Qt.ItemIsEnabled | Qt.ItemIsSelectable | Qt.ItemIsEditable
        else:
            return Qt.ItemIsEnabled | Qt.ItemIsSelectable

class MyLineEdit(QtWidgets.QLineEdit):
    def __init__(self, parent=None):
        super(MyLineEdit, self).__init__(parent)

    def focusInEvent(self, e):
        print("focusin editor")
        QTimer.singleShot(0, self.deselect)
        QTimer.singleShot(0, self.selectAll)

    def focusOutEvent(self, e):
        print("focusout editor")
        QTimer.singleShot(0, self.deselect)


class LineEditFileDelegate(QtWidgets.QStyledItemDelegate):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.editor = None
        # self.proxy=proxy
        self.last_data=None

    def paint(self, painter, option, index):
        if isinstance(self.parent(), QtWidgets.QAbstractItemView):
            self.parent().openPersistentEditor(index)
        QtWidgets.QStyledItemDelegate.paint(self, painter, option, index)

    def createEditor(self, parent, option, index):
        self.view = parent.parent()
        self.editor=MyLineEdit(parent)
        return self.editor


    def setEditorData(self, editor, index):
        print("setEditorData")
        v = index.data(Qt.EditRole)
        self.last_data = v
        self.editor.setText(v)

    def setModelData(self, editor, model, index):
        ix = editor.text()
        if not(ix):
            return 
        model.setData(index, ix, Qt.EditRole)

    def updateEditorGeometry(self, editor, option, index):
        editor.setGeometry(option.rect)


    def check_data(self):
        ix = self.editor.text()
        print(ix)
        if (ix) and(ix.lower()[0]=="s"):
            return True
        else:
            return False

    def eventFilter(self, editor, event):
        # if event.type() in [QEvent.FocusAboutToChange,  QEvent.FocusOut]:
        #     return False

        if event.type() == QEvent.KeyPress:
            key = event.key()
            mod = int(event.modifiers())
            if event.key() == Qt.Key_Return:
                if self.check_data():
                    # self.last_data = self.editor.text()
                    self.commitData.emit(editor)
                    self.closeEditor.emit(editor, QAbstractItemDelegate.NoHint)

                # # Don't emit closeEditor, select contents instead
                editor.selectAll()
                return False
            if event.key() == Qt.Key_Escape:
                #editor.setText( self.last_data)
                self.closeEditor.emit(editor, QAbstractItemDelegate.NoHint)
                return False

        QtWidgets.QStyledItemDelegate.eventFilter(self, editor, event)
        return False


class SchedulesViewer(QTableView):

    def __init__(self, test_data=None, parent=None):
        QTableView.__init__(self, parent)

        # self.setContextMenuPolicy(Qt.CustomContextMenu)
        # self.customContextMenuRequested.connect(self.schedule_context_menu)
        self.schedule_model = ScheduleModel(test_data)

        self.proxyModel = QSortFilterProxyModel(self)
        self.proxyModel.setSourceModel(self.schedule_model)
        self.proxyModel.setDynamicSortFilter(True)

        self.setModel(self.proxyModel)

        """
        HAVING LIMITS TO THE AMOUNT OF WIDGETS TABLE VIEW CAN HANDEL
        """

        self.setItemDelegateForColumn(2, LineEditFileDelegate(self))
        
        self.setSortingEnabled(True)
        self.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.horizontalHeader().setStretchLastSection(True)
        self.verticalHeader().hide()
        self.setSelectionMode(QAbstractItemView.SingleSelection)
        self.proxyModel.sort(0, Qt.AscendingOrder)
        self.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.setEditTriggers(QAbstractItemView.DoubleClicked)

        self.setSelectionMode(QAbstractItemView.SingleSelection)


        self.show()


if __name__ == "__main__":
    import sys
    from PySide2.QtWidgets import QApplication

    app = QApplication(sys.argv)

    test_data = [[x*3, idx, x] for idx,x in enumerate('abcde')]
    addressWidget = SchedulesViewer(test_data)
    addressWidget.show()
    sys.exit(app.exec_())

`


Tags: selfnoneeventdataindexreturnifinit