PyQt5 如何在 QTableWidget 上按回车键并转到下面的单元格?
PyQt5 How to press enter on a QTableWidget and go to the cell below?
我正在尝试使用 PyQt5 和 Python.
来制作一个像 excel 表格一样的 QTableWidget
为此,我想激活按下回车键的选项,下面的单元格将成为焦点。
如何操作?
这是我的尝试:
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())
我在 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)
祝你好运。
您的尝试没有成功,因为您想要响应的 keyPressEvent
必须由 table 接收,这不是您的情况,因为您显然正在尝试这样做来自包含 table.
的父 window
当按键事件发生时,当前 focused 小部件接收它;如果该小部件对该事件不感兴趣,它将被发送回该小部件的父级,依此类推,直到某个小部件实际上能够对该事件做出反应并且可能接受它;一旦事件被接受,父控件将不会收到它。
虽然一些小部件只是忽略一些或任何键盘事件(例如,QLabel),但其他小部件只是“吃掉”几乎所有事件,这就是像 QTableWidget 这样的项目视图的情况。如果 table 有焦点,当它收到 return 键事件时它将接受它,该事件将不再传播,这就是为什么你无法从你的 keyPressEvent
覆盖。
最常用的解决方案是子class table 并为 class 实施 keyPressEvent
(如 中所述)。
一个常见的替代方法是使用事件过滤器,如果您使用的是在 Designer 中创建的 GUI,这将非常有用,因为它允许添加小功能而无需 subclass 和使用提升小部件。
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)
最后,还有“猴子补丁”,只要需要非常简单的 class 修改就可以使用它,而无需创建子 classes。这也适用于设计器创建的 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)
我正在尝试使用 PyQt5 和 Python.
来制作一个像 excel 表格一样的 QTableWidget为此,我想激活按下回车键的选项,下面的单元格将成为焦点。
如何操作?
这是我的尝试:
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())
我在 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)
祝你好运。
您的尝试没有成功,因为您想要响应的 keyPressEvent
必须由 table 接收,这不是您的情况,因为您显然正在尝试这样做来自包含 table.
当按键事件发生时,当前 focused 小部件接收它;如果该小部件对该事件不感兴趣,它将被发送回该小部件的父级,依此类推,直到某个小部件实际上能够对该事件做出反应并且可能接受它;一旦事件被接受,父控件将不会收到它。
虽然一些小部件只是忽略一些或任何键盘事件(例如,QLabel),但其他小部件只是“吃掉”几乎所有事件,这就是像 QTableWidget 这样的项目视图的情况。如果 table 有焦点,当它收到 return 键事件时它将接受它,该事件将不再传播,这就是为什么你无法从你的 keyPressEvent
覆盖。
最常用的解决方案是子class table 并为 class 实施 keyPressEvent
(如
一个常见的替代方法是使用事件过滤器,如果您使用的是在 Designer 中创建的 GUI,这将非常有用,因为它允许添加小功能而无需 subclass 和使用提升小部件。
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)
最后,还有“猴子补丁”,只要需要非常简单的 class 修改就可以使用它,而无需创建子 classes。这也适用于设计器创建的 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)