Поймать клавишу ESC при редактировании QTableView - PullRequest
0 голосов
/ 07 ноября 2018

Попытка выяснить, как поймать строку в редактируемом QTableView, была отменена. Например, если я редактирую недавно вставленную строку в QTableView и ESC, клавиши со стрелками вверх / вниз были нажаты, мне нужно удалить строку, потому что (на мой взгляд) был отменен. Также справедливо, если пользователь щелкает по строке. Я не могу опубликовать код, так как понятия не имею, как реализовать что-то подобное. Есть идеи?

1 Ответ

0 голосов
/ 08 ноября 2018

У меня есть пример того, во что я верю, то, что вы хотите (по крайней мере, для нажатия клавиши). Оттуда вы можете сделать что-то похожее для вопроса щелчка.

Мое решение использует пользовательский QItemDelegate, который переопределяет метод eventFilter. Также он использует простую модель (потому что вы хотите использовать QTableView), использование сигнала layoutChanged на модели связано с функциональностью примера, прочитайте документы для более подходящих функций добавления / удаления данных в соответствии с вашими потребностями.

Надеюсь, это поможет.

Образец пользовательского интерфейса:

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'test.ui',
# licensing of 'test.ui' applies.
#
# Created: Wed Nov  7 16:10:12 2018
#      by: pyside2-uic  running on PySide2 5.11.0
#
# WARNING! All changes made in this file will be lost!

from PySide2 import QtCore, QtGui, QtWidgets

class Ui_Test(object):
    def setupUi(self, Test):
        Test.setObjectName("Test")
        Test.resize(538, 234)
        self.horizontalLayout = QtWidgets.QHBoxLayout(Test)
        self.horizontalLayout.setObjectName("horizontalLayout")
        self.gridLayout = QtWidgets.QGridLayout()
        self.gridLayout.setObjectName("gridLayout")
        self.tableView = QtWidgets.QTableView(Test)
        self.tableView.setObjectName("tableView")
        self.gridLayout.addWidget(self.tableView, 0, 0, 1, 1)
        self.addRow = QtWidgets.QPushButton(Test)
        self.addRow.setObjectName("addRow")
        self.gridLayout.addWidget(self.addRow, 0, 1, 1, 1)
        self.horizontalLayout.addLayout(self.gridLayout)

        self.retranslateUi(Test)
        QtCore.QMetaObject.connectSlotsByName(Test)

    def retranslateUi(self, Test):
        Test.setWindowTitle(QtWidgets.QApplication.translate("Test", "Dialog", None, -1))
        self.addRow.setText(QtWidgets.QApplication.translate("Test", "add row", None, -1))

Фактические участвующие классы (я использую PySide2):

from PySide2 import QtWidgets, QtCore, QtGui
from _test import Ui_Test


class MyDialog(QtWidgets.QDialog):
    def __init__(self, parent = None):
        super(MyDialog, self).__init__(parent = parent)
        self.ui = Ui_Test()
        self.ui.setupUi(self)
        self._model = MyModel([["first row 1 col", "first row 2"],["second row 1", "second row 2"]])
        self.ui.tableView.setModel(self._model)
        self.ui.addRow.clicked.connect(self._model.addRow)
        self.ui.tableView.setItemDelegate(MyDelegate(self.ui.tableView))
        # this is crucial: we need to be sure that the selection is single on the view
        self.ui.tableView.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectItems)
        self.ui.tableView.setSelectionMode(QtWidgets.QAbstractItemView.SingleSelection)


class MyModel(QtCore.QAbstractTableModel):
    def __init__(self, table_data = None, parent = None):
        super(MyModel, self).__init__(parent = parent)
        if not table_data: self._data = []
        self._data = table_data

    def rowCount(self, parent = None):
        return len(self._data)

    def columnCount(self, parent = None):
        return 2

    def addRow(self):
        self._data.append(["new item", "new item"])
        self.layoutChanged.emit()

    def removeRow(self, row):
        if 0 <= row < self.rowCount(): 
            del self._data[row]
            self.layoutChanged.emit()

    def data(self, index, role = QtCore.Qt.DisplayRole):
        if index.isValid():
            if role == QtCore.Qt.DisplayRole:
                row = index.row()
                col = index.column()
                return self._data[row][col]

    def setData(self, index, value, role = QtCore.Qt.EditRole):
        if index.isValid():
            if role == QtCore.Qt.EditRole:
                row = index.row()
                col = index.column()
                self._data[row][col] = str(value)
                return True
            else:
                return False
        else:
            return False

    def flags(self, index):
        return QtCore.Qt.ItemIsSelectable|QtCore.Qt.ItemIsEditable|QtCore.Qt.ItemIsEnabled


class MyDelegate(QtWidgets.QItemDelegate):
    def __init__(self, parent = None):
        super(MyDelegate, self).__init__(parent)
        self.view = parent

    def eventFilter(self, editor, event):
        # there is a lot of checking in order to identify the desired situation
        # and avoid errors
        if isinstance(event, QtGui.QKeyEvent):
            if event.type() == QtCore.QEvent.KeyPress:
                if event.key() == QtCore.Qt.Key_Escape:
                    # we should have a list here of length one (due to selection restrictions on the view)
                    index = self.view.selectedIndexes()
                    if index:
                        if index[0].isValid():
                            row = index[0].row()
                            self.view.model().removeRow(row)


        return super(MyDelegate, self).eventFilter(editor, event)

if __name__ == '__main__':
    app = QtWidgets.QApplication()
    diag = MyDialog()
    diag.show()
    app.exec_()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...