代码之家  ›  专栏  ›  技术社区  ›  JokerMartini

在QTableView中选择一行将激活列编辑

  •  0
  • JokerMartini  · 技术社区  · 6 年前

    如何使第二列在编辑模式下活动,只要在tableview中选择一行,如下面的gif所示?我正在用python/pyside重新创建这个。

    理想情况下,我想使用某种类型的项委托,这样我就可以轻松地处理列单元格中的keyPressEvents并添加自定义(X)清除按钮。但是,我不知道在使用ItemModels时如何使用这样的委托。因此,任何有助于实现这一任务的人都将不胜感激。

    class ExampleDelegate(QtGui.QStyledItemDelegate):
        def createEditor(self, parent, option, index):
            line_edit = QtGui.QLineEdit(parent)
            return line_edit
    

    enter image description here

    enter image description here

    import os, sys
    from PySide import QtGui, QtCore
    
    
    class HotkeyItem():
        def __init__(self, command, shortcut):
            self.command = command
            self.shortcut = shortcut
    
    
    class HotkeysModel(QtCore.QAbstractTableModel):
    
        def __init__(self):
            super(HotkeysModel, self).__init__()
            self.items = []
            self.headers = ['Command','Hotkey']
    
        def clear(self):
            self.beginResetModel()
            self.items = []
            self.endResetModel()
    
        def rowCount(self, parent=QtCore.QModelIndex()):
            if parent.isValid():
                return 0
            return len(self.items)
    
        def headerData(self, section, orientation, role=QtCore.Qt.DisplayRole):
            if orientation == QtCore.Qt.Horizontal:
                if role == QtCore.Qt.DisplayRole:
                    cnt = len(self.headers)
                    if section < cnt:
                        return self.headers[section]
            return None
    
        def columnCount(self, parent=QtCore.QModelIndex()):
            if parent.isValid():
                return 0
            return len(self.headers)
    
        def index(self, row, column, parent=QtCore.QModelIndex()):
            return self.createIndex(row, column, parent)
    
        def addItem(self, item):
            self.beginInsertRows(QtCore.QModelIndex(), self.rowCount(), self.rowCount())
            self.items.append(item)
            self.endInsertRows()
    
        def data(self, index, role=QtCore.Qt.DisplayRole):
            if not index.isValid():
                return
    
            row = index.row()
            col = index.column()
    
            if 0 <= row < self.rowCount():
                item = self.items[row]
    
                if role == QtCore.Qt.DisplayRole:
                    if col == 0:
                        return getattr(item, 'command', 'N/A')
                    elif col == 1:
                        return getattr(item, 'shortcut', '')
    
                if role == QtCore.Qt.BackgroundRole:
                    shortcuts = filter(None, [x.shortcut for x in self.items])
                    dups = shortcuts.count(getattr(item, 'shortcut', ''))
                    if dups > 1:
                        return QtGui.QBrush(QtGui.QColor(255, 50, 50, 255))
    
                elif role == QtCore.Qt.FontRole:
                    shortcuts = filter(None, [x.shortcut for x in self.items])
                    dups = shortcuts.count(getattr(item, 'shortcut', ''))
                    if dups > 1:
                        fnt = QtGui.QFont()
                        fnt.setBold(True)
                        fnt.setItalic(True)
                        return fnt
    
            return None
    
        def flags(self, index):
            if not index.isValid():
                return 0
            return QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable
    
    
    class Example(QtGui.QWidget):
        def __init__(self, parent=None):
            super(Example, self).__init__(parent)
            self.resize(600, 400)
    
            model = HotkeysModel()
    
            proxyModel = QtGui.QSortFilterProxyModel()
            proxyModel.setFilterKeyColumn(0)
            proxyModel.setSortCaseSensitivity(QtCore.Qt.CaseInsensitive)
            proxyModel.setSourceModel(model)
    
            self.uiView = QtGui.QTableView()
            self.uiView.setSortingEnabled(True)
            self.uiView.setModel(proxyModel)
            self.uiView.setAlternatingRowColors(True)
            self.uiView.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows)
            self.uiView.setSelectionMode(QtGui.QAbstractItemView.SingleSelection)
            self.uiView.setEditTriggers(QtGui.QAbstractItemView.NoEditTriggers)
            self.uiView.verticalHeader().hide()
            self.uiView.horizontalHeader().show()
    
            lay = QtGui.QVBoxLayout()
            lay.addWidget(self.uiView)
            self.setLayout(lay)
    
            self.populate()
    
            # connections
            selection = self.uiView.selectionModel()
            selection.currentRowChanged.connect(self.selection_changed)
    
    
    # ui->tableView->setCurrentIndex(index);
    # ui->tableView->edit(index);
    
        def selection_changed(self, index):
            if index.isValid():
                row = index.row()
                self.uiView.setCurrentIndex(index)
                self.uiView.edit(index)
    
    
        def populate(self):
            model = self.uiView.model().sourceModel()
            model.clear()
    
            items = [
                HotkeyItem(command='Save', shortcut='Ctrl+S'),
                HotkeyItem(command='Open', shortcut='Ctrl+O'),
                HotkeyItem(command='Close', shortcut='Ctrl+Q'),
                HotkeyItem(command='Align Top', shortcut=''),
                HotkeyItem(command='Align Bottom', shortcut=''),
                HotkeyItem(command='Align Left', shortcut=''),
                HotkeyItem(command='Align Right', shortcut=''),
                HotkeyItem(command='Align Center', shortcut='Ctrl+O')
            ]
    
            for x in items:
                model.addItem(x)
    
            self.uiView.sortByColumn(0, QtCore.Qt.AscendingOrder)
            self.uiView.resizeColumnsToContents()
    
    
    def main():
        app = QtGui.QApplication(sys.argv)
        ex = Example()
        ex.show()
        sys.exit(app.exec_())
    
    
    if __name__ == '__main__':
        main()
    
    1 回复  |  直到 6 年前
        1
  •  2
  •   eyllanesc RAHUL KUMAR    6 年前

    问题的一部分是,要使项可编辑,它必须有标志 QtCore.Qt.ItemIsEditable

    在Qt5中,clear按钮已经实现,并且只有使用 setClearButtonEnabled(True) this answer .

    setData() 方法。

    import os
    import sys
    from PySide import QtGui, QtCore
    
    
    class LineEdit(QtGui.QLineEdit):
        def __init__(self, parent=None):
            super(LineEdit, self).__init__(parent)
            btnSize = self.sizeHint().height() - 5
            self.clearButton = QtGui.QToolButton(self)
            icon = QtGui.QIcon("clear.png")
            self.clearButton.setIcon(icon)
            self.clearButton.setCursor(QtCore.Qt.ArrowCursor)
            self.clearButton.setStyleSheet("QToolButton { border: none; padding: 2px}")
            self.clearButton.setFixedSize(btnSize, btnSize)
            self.clearButton.hide()
            frameWidth = self.style().pixelMetric(QtGui.QStyle.PM_DefaultFrameWidth)
            self.setStyleSheet("QLineEdit{{ padding-right: {}px }}".format(btnSize - frameWidth))
            self.setMinimumHeight(self.sizeHint().height())
            self.clearButton.clicked.connect(self.clear)
            self.textChanged.connect(self.onTextChanged)
    
        def resizeEvent(self, event):
            frameWidth = self.style().pixelMetric(QtGui.QStyle.PM_DefaultFrameWidth)
            self.clearButton.move(self.width() - self.clearButton.width() - frameWidth, 0)
    
        def onTextChanged(self, text):
            self.clearButton.setVisible(text != "")
    
    
    class Delegate(QtGui.QStyledItemDelegate):
        def createEditor(self, parent, option, index):
            editor = LineEdit(parent)
            font = index.data(QtCore.Qt.FontRole)
            editor.setFont(font)
            return editor
    
        def setEditorData(self, editor, index):
            text = index.data()
            editor.setText(text)
    
        def setModelData(self, editor, model, index):
            model.setData(index, editor.text())
    
    class HotkeyItem():
        def __init__(self, command, shortcut):
            self.command = command
            self.shortcut = shortcut
    
    
    class HotkeysModel(QtCore.QAbstractTableModel):
        def __init__(self):
            super(HotkeysModel, self).__init__()
            self.items = []
            self.headers = ['Command','Hotkey']
    
        def clear(self):
            self.beginResetModel()
            self.items = []
            self.endResetModel()
    
        def rowCount(self, parent=QtCore.QModelIndex()):
            if parent.isValid():
                return 0
            return len(self.items)
    
        def headerData(self, section, orientation, role=QtCore.Qt.DisplayRole):
            if orientation == QtCore.Qt.Horizontal:
                if role == QtCore.Qt.DisplayRole:
                    cnt = len(self.headers)
                    if section < cnt:
                        return self.headers[section]
            return None
    
        def columnCount(self, parent=QtCore.QModelIndex()):
            if parent.isValid():
                return 0
            return len(self.headers)
    
        def addItem(self, item):
            self.beginInsertRows(QtCore.QModelIndex(), self.rowCount(), self.rowCount())
            self.items.append(item)
            self.endInsertRows()
    
        def data(self, index, role=QtCore.Qt.DisplayRole):
            if not index.isValid():
                return 
    
            row = index.row()
            col = index.column()
    
            if 0 <= row < self.rowCount():
                item = self.items[row]
    
                if role == QtCore.Qt.DisplayRole:
                    if col == 0:
                        return getattr(item, 'command', 'N/A')
                    elif col == 1:
                        return getattr(item, 'shortcut', '')
    
                if role == QtCore.Qt.BackgroundRole:
                    shortcuts = filter(None, [x.shortcut for x in self.items])
                    dups = shortcuts.count(getattr(item, 'shortcut', ''))
                    if dups > 1:
                        return QtGui.QBrush(QtGui.QColor(255, 50, 50, 255))
    
                elif role == QtCore.Qt.FontRole:
                    shortcuts = filter(None, [x.shortcut for x in self.items])
                    dups = shortcuts.count(getattr(item, 'shortcut', ''))
                    if dups > 1:
                        fnt = QtGui.QFont()
                        fnt.setBold(True)
                        fnt.setItalic(True)
                        return fnt
    
        def setData(self, index, value, role=QtCore.Qt.EditRole):
            if index.isValid():
                row = index.row()
                col = index.column()
                if 0 <= row < self.rowCount() and 0 <= col < self.columnCount():
                    it = self.items[row]
                    if col == 0:
                        it.command = value
                    elif col == 1:
                        it.shortcut = value
                    return True
            return False
    
        def flags(self, index):
            fl = QtCore.Qt.NoItemFlags
            if index.isValid():
                fl |= QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable
                if index.column() == 1:
                    fl |= QtCore.Qt.ItemIsEditable
            return fl
    
    
    class Example(QtGui.QWidget):
        def __init__(self, parent=None):
            super(Example, self).__init__(parent)
            self.resize(600, 400)
    
            model = HotkeysModel()
    
            proxyModel = QtGui.QSortFilterProxyModel()
            proxyModel.setFilterKeyColumn(0)
            proxyModel.setSortCaseSensitivity(QtCore.Qt.CaseInsensitive)
            proxyModel.setSourceModel(model)
    
            self.uiView = QtGui.QTableView()
            self.uiView.setSortingEnabled(True)
            self.uiView.setModel(proxyModel)
            self.uiView.setAlternatingRowColors(True)
            delegate = Delegate(self)
            self.uiView.setItemDelegateForColumn(1, delegate)
            self.uiView.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows)
            self.uiView.setSelectionMode(QtGui.QAbstractItemView.SingleSelection)
            self.uiView.setEditTriggers(QtGui.QAbstractItemView.NoEditTriggers)
            self.uiView.verticalHeader().hide()
            self.uiView.horizontalHeader().show()
    
            lay = QtGui.QVBoxLayout()
            lay.addWidget(self.uiView)
            self.setLayout(lay)
            self.populate()
    
            # connections
            selection = self.uiView.selectionModel()
            selection.currentChanged.connect(self.openEditor)
            self.uiView.clicked.connect(self.openEditor)
    
        def openEditor(self, index):
            if index.isValid():
                ix = index.sibling(index.row(), 1)
                self.uiView.setCurrentIndex(ix)
                self.uiView.edit(ix)
    
        def populate(self):
            model = self.uiView.model().sourceModel()
            model.clear()
    
            items = [
                HotkeyItem(command='Save', shortcut='Ctrl+S'),
                HotkeyItem(command='Open', shortcut='Ctrl+O'),
                HotkeyItem(command='Close', shortcut='Ctrl+Q'),
                HotkeyItem(command='Align Top', shortcut=''),
                HotkeyItem(command='Align Bottom', shortcut=''),
                HotkeyItem(command='Align Left', shortcut=''),
                HotkeyItem(command='Align Right', shortcut=''),
                HotkeyItem(command='Align Center', shortcut='Ctrl+O')
            ]
    
            for x in items:
                model.addItem(x)
    
            self.uiView.sortByColumn(0, QtCore.Qt.AscendingOrder)
            self.uiView.resizeColumnsToContents()
    
    
    def main():
        app = QtGui.QApplication(sys.argv)
        ex = Example()
        ex.show()
        sys.exit(app.exec_())
    
    
    if __name__ == '__main__':
        main()