[英]PyQt5 How to press enter on a QTableWidget and go to the cell below?
我正在尝试使用 PyQt5 和 Python 来详细说明一个 QTableWidget,如 Excel 表格。
为此,我想激活按下回车按钮的选项,下面的单元格会成为焦点。
这该怎么做?
这是我的尝试:
def keyPressEvent(self, event):
super().keyPressEvent(event)
row = self.tableWidget.currentRow()
col = self.tableWidget.currentColumn()
if event.key() == Qt.Key_Enter and row < self.tableWidget.rowCount():
row += 1
self.tableWidget.setCurrentCell(row, col)
self.tableWidget.edit(self.tableWidget.currentIndex())
您的尝试没有成功,因为您想要做出反应的keyPressEvent
必须由表接收,这不是您的情况,因为您显然试图从包含该表的父窗口执行此操作。
当一个键事件发生时,当前聚焦的小部件接收它; 如果该小部件对该事件不感兴趣,则将其发送回该小部件的父级,依此类推,直到某个小部件实际上能够对该事件做出反应并可能接受它; 一旦事件被接受,父小部件将不会收到它。
虽然一些小部件只是忽略一些或任何键盘事件(例如,QLabel),但其他小部件几乎“吃”任何事件,这就是像 QTableWidget 这样的项目视图的情况。 如果表具有焦点,当它收到返回键事件时,它将接受它,该事件将不再传播,这就是您无法从keyPressEvent
覆盖接收它的原因。
最常用的解决方案是对表进行子类化并为该类实现keyPressEvent
(如Gibus 给出的答案中所述)。
一个常见的替代方法是使用事件过滤器,如果您使用在 Designer 中创建的 GUI,它非常有用,因为它允许添加小功能,而无需子类化和使用升级的小部件。
class MyWindow(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
self.tableWidget = QtWidgets.QTableWidget
self.setCentralWidget(self.tableWidget)
self.tableWidget.installEventFilter(self)
def eventFilter(self, source, event):
if (event.type() == QtCore.QEvent.KeyPress and
event.key() in (QtCore.Qt.Key_Return, QtCore.Qt.Key_Enter)):
# ensure that the table receives the key event first
res = super().eventFilter(source, event)
current = self.tableWidget.currentIndex()
nextIndex = current.sibling(current.row() + 1, current.column())
if nextIndex.isValid():
self.tableWidget.setCurrentIndex(nextIndex)
self.tableWidget.edit(nextIndex)
return res
return super().eventFilter(source, event)
最后,还有“猴子补丁”,它可以在需要非常简单的类修改时使用,而无需创建子类。 这也适用于 Designer 创建的 GUI。
请注意,猴子补丁并非适用于所有情况:某些方法不能被覆盖,尤其是在实例已被覆盖后; 值得注意的是,PyQt 使用缓存函数绑定,这意味着如果在覆盖它之前调用了基本实现方法,则之后无法覆盖它。
class MyWindow(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
self.tableWidget = QtWidgets.QTableWidget
self.setCentralWidget(self.tableWidget)
self.tableWidget.keyPressEvent = self.tableKeyPressEvent
def tableKeyPressEvent(self, event):
# call the base implementation, do *not* use super()!
QtWidgets.QTableWidget.keyPressEvent(self.tableWidget, event)
if event.key() in (QtCore.Qt.Key_Return, QtCore.Qt.Key_Enter):
current = self.tableWidget.currentIndex()
nextIndex = current.sibling(current.row() + 1, current.column())
if nextIndex.isValid():
self.tableWidget.setCurrentIndex(nextIndex)
self.tableWidget.edit(nextIndex)
我在PySide2 中做过一段时间,但它应该大致相同。
首先扩展QTableWidget:
class FooTable(QTableWidget):
def __init__(self):
super().__init__()
然后将以下内容作为方法实现:
def keyPressEvent(self, event: QtGui.QKeyEvent):
if event.key() == Qt.Key_Return: # 16777220 # Enter
col = self.currentColumn()
row = self.currentRow()
self.setCurrentCell(row + 1, col)
祝你好运。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.