问题
I have a QTableWidget generated by QTDesigner in which I want to set some custom key press events.
when current cell is in edit mode and if user presses Tab key, it moves to next cell in edit mode but i just want it move to next cell selected and not in edit mode.
when current cell is in edit mode and if user presses Left, right, up, down- it should move to corresponding cell in select mode again and not in edit mode.
both of this works well right now if current cell is just selected and not in edit mode. but how can i set this customized event?
Thanks!!
Code Generated by UI Designer:
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_())
My Script:
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:
You can reimplement the closeEditor() method, which is responsible of the action that the item view will take when an item editing has been completed.
In this example I'll overwrite the method as you did with the keypress event, but I strongly suggest you to use subclasses and implement the overrides in them, as the code would be cleaner and can avoid confusion between existing functions and/or overwritten methods.
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)
# ...
Since you also want to move to the items using the arrow keys even while in editing state, you can only do this by installing a custom item delegate that checks for keyboard events in the editor.
I have to warn you, though: don't do this.
Left and right arrow keys are always used for cursor navigation when editing text, changing this behavior is absolutely discouraged.
It's unintuitive, unnatural, uncomfortable, against any common and expected behavior, and will make users accustomed to keyboard navigation very, very, very annoyed. I've seen a similar behavior in a program in the past, and I can tell you that it's not good and it's very irritating.
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)
In case it wasn't clear enough, you should not use this :-)
来源:https://stackoverflow.com/questions/60954886/how-can-i-set-custom-key-board-key-press-event-in-qtablewidget-python