Как я могу установить событие нажатия клавиш на пользовательской клавиатуре в Qtablewidget Python? - PullRequest
0 голосов
/ 31 марта 2020

У меня есть QTableWidget, сгенерированный QTDesigner, в котором я хочу установить некоторые пользовательские события нажатия клавиш.

  1. , когда текущая ячейка находится в режиме редактирования, и если пользователь нажимает клавишу Tab, она перемещается к следующей ячейке в режиме редактирования, но я просто хочу, чтобы она перемещалась к следующей выбранной ячейке, а не в режиме редактирования.

  2. , когда текущая ячейка находится в режиме редактирования и если пользователь нажимает влево, вправо, вверх, вниз - она ​​должна переместиться в соответствующую ячейку в режиме выбора снова, а не в режиме редактирования.

и то, и другое работает хорошо, если текущая ячейка только что выбрана и не находится в режиме редактирования. но как я могу установить это настроенное событие?

Спасибо !!

Код, сгенерированный дизайнером пользовательского интерфейса:

from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(428, 285)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.tableWidget = QtWidgets.QTableWidget(self.centralwidget)
        self.tableWidget.setGeometry(QtCore.QRect(20, 20, 391, 231))
        self.tableWidget.setEditTriggers(QtWidgets.QAbstractItemView.AnyKeyPressed|QtWidgets.QAbstractItemView.DoubleClicked|QtWidgets.QAbstractItemView.EditKeyPressed|QtWidgets.QAbstractItemView.SelectedClicked)
        self.tableWidget.setRowCount(5)
        self.tableWidget.setColumnCount(3)
        self.tableWidget.setObjectName("tableWidget")
        item = QtWidgets.QTableWidgetItem()
        self.tableWidget.setHorizontalHeaderItem(0, item)
        item = QtWidgets.QTableWidgetItem()
        self.tableWidget.setHorizontalHeaderItem(1, item)
        item = QtWidgets.QTableWidgetItem()
        self.tableWidget.setHorizontalHeaderItem(2, item)
        self.tableWidget.horizontalHeader().setVisible(True)
        self.tableWidget.verticalHeader().setVisible(False)
        MainWindow.setCentralWidget(self.centralwidget)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

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

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        item = self.tableWidget.horizontalHeaderItem(0)
        item.setText(_translate("MainWindow", "Name"))
        item = self.tableWidget.horizontalHeaderItem(1)
        item.setText(_translate("MainWindow", "Age"))
        item = self.tableWidget.horizontalHeaderItem(2)
        item.setText(_translate("MainWindow", "City"))


if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    MainWindow = QtWidgets.QMainWindow()
    ui = Ui_MainWindow()
    ui.setupUi(MainWindow)
    MainWindow.show()
    sys.exit(app.exec_())

Мой сценарий:

from PyQt5 import QtWidgets, QtCore
from demo import Ui_MainWindow

class DemoTable(QtWidgets.QMainWindow, Ui_MainWindow):                 
    def __init__(self):
        super(DemoTable, self).__init__()
        self.setupUi(self) 

        #KeyPressEvent
        self.tableWidget.keyPressEvent = self.KeyPressed

    def KeyPressed(self,event):
        if event.key() == QtCore.Qt.Key_Left:
            print('Left Key Pressed')
        elif event.key() == QtCore.Qt.Key_Right:
            print('Right Key Pressed')
        elif event.key() == QtCore.Qt.Key_Tab:
            print('Tab Key Pressed')
        return QtWidgets.QTableWidget.keyPressEvent(self.tableWidget, event)

if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    demowindow = DemoTable()   
    demowindow.show()
    sys.exit(app.exec_())

1 Ответ

0 голосов
/ 31 марта 2020

Вы можете переопределить метод closeEditor(), который отвечает за действие, которое будет выполнено представлением элемента после завершения редактирования элемента.

В этом примере я переписать метод, как вы это делали с событием нажатия клавиши, но я настоятельно рекомендую вам использовать подклассы и реализовывать в них переопределения, так как код будет чище и поможет избежать путаницы между существующими функциями и / или перезаписанными методами.

class DemoTable(QtWidgets.QMainWindow, Ui_MainWindow):                 
    def __init__(self):
        super(DemoTable, self).__init__()
        self.setupUi(self) 

        #KeyPressEvent
        self.tableWidget.keyPressEvent = self.KeyPressed
        self.tableWidget.closeEditor = self.closeEditor

    def closeEditor(self, editor, hint):
        if hint in (QtWidgets.QItemDelegate.EditNextItem, 
            QtWidgets.QItemDelegate.EditPreviousItem):
                # if the hint is to edit the next or previous item, ignore it
                newHint = QtWidgets.QItemDelegate.NoHint
        else:
            newHint = hint

        # call the base implementation with the new hint
        QtWidgets.QTableWidget.closeEditor(self.tableWidget, editor, newHint)

        if hint == QtWidgets.QItemDelegate.EditNextItem:
            # find the next item to focus on
            index = self.tableWidget.moveCursor(self.tableWidget.MoveNext, 
                QtCore.Qt.NoModifier)
        elif hint  == QtWidgets.QItemDelegate.EditPreviousItem:
            # find the previous item to focus on
            index = self.tableWidget.moveCursor(self.tableWidget.MovePrevious, 
                QtCore.Qt.NoModifier)
        else:
            return
        # set the new current item
        self.tableWidget.setCurrentIndex(index)

    # ...

Поскольку вы также хотите переходить к элементам с помощью клавиш со стрелками даже в состоянии редактирования , вы можете сделать это только путем установки пользовательского делегата элемента, который проверяет события клавиатуры в редакторе.

Я должен предупредить вас, хотя: не делайте этого .
Клавиши со стрелками влево и вправо всегда используются для перемещения курсора при редактировании текста, изменении это поведение абсолютно не рекомендуется.
Это неинтуитивно, неестественно, неудобно, против любого обычного и ожидаемого поведения, и сделает пользователей привык к навигации с клавиатуры очень, очень , очень раздражен. Я видел подобное поведение в программе в прошлом, и я могу сказать вам, что это не хорошо и это очень раздражает.

class DelegateYouShouldNotUse(QtWidgets.QStyledItemDelegate):
    def eventFilter(self, source, event):
        if isinstance(source, QtWidgets.QLineEdit) and event.type() == QtCore.QEvent.KeyPress:
            if event.key() == QtCore.Qt.Key_Right:
                # tell the view to store the current data
                self.commitData.emit(source)
                # and to move to the next item (since we've changed the
                # behavior of the closeEditor *slot* of the table, it
                # will only move to the item, without starting editing
                self.closeEditor.emit(source, self.EditNextItem)
                return True
            elif event.key() == QtCore.Qt.Key_Left:
                self.commitData.emit(source)
                self.closeEditor.emit(source, self.EditPreviousItem)
                return True
        return super().eventFilter(source, event)


class DemoTable(QtWidgets.QMainWindow, Ui_MainWindow):                 
    def __init__(self):
        super(DemoTable, self).__init__()
        # ...
        self.veryBadDelegate = DelegateYouShouldNotUse(self.tableWidget)
        self.tableWidget.setItemDelegate(self.veryBadDelegate)

В случае, если это не было не достаточно ясно, вы должны не использовать это: -)

...