繁体   English   中英

PyQt5 如何在 QTableWidget 上按 Enter 并转到下面的单元格?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM