QTableView 拦截 Key_Down 和 Key_Up 事件

2 投票
2 回答
2895 浏览
提问于 2025-04-18 15:49

我正在尝试在 QTableView 上实现一些功能。所以,我开始重写它的 keyPressEvent 方法,这在很多地方都有介绍:

if e.key() == QtCore.Qt.Key_F2 and self.tableau.hasFocus():
    blabla

elif e.key() == QtCore.Qt.Key_Return and self.tableau.hasFocus():
    blabla

#TEST
elif e.key() == QtCore.Qt.Key_Right:
    print("right")
elif e.key() == QtCore.Qt.Key_Down:
    print("down")
else:
    print("waza")

我可以处理 F2 和回车键的事件,它们都能正常工作。但是向下箭头键的事件却不行!向右箭头键可以,但向下的却不行。我觉得这可能是因为 QTableWidget “拦截”了一些事件。例如,当按下普通字母键时,也没有事件被“发出”。

我想要访问所有的事件(或者至少是向上和向下的事件),我该怎么做呢?

编辑:

我使用的视图基本上是一个 QTableView,我对它做了一些修改:

class ViewPerso(QtGui.QTableView):

    def __init__(self, parent=None):
        super(ViewPerso, self).__init__(parent)

        self.parent = parent


    def currentChanged(self, current, previous):

        index = current.sibling(current.row(), 4)

        try:
            if not index.data() or len(self.parent.vidsSelected()) > 1:
                return
        except AttributeError:
            pass

        self.clicked.emit(current)
        self.scrollTo(current)


    def keyboardSearch(self, search):

        pass

我不使用 QTableWidget,因为它不能满足我的需求。我还对视图的代理进行了子类化,但通常情况下(正常情况下),应该没有东西会干扰。

这是我使用视图的方式:我加载一个模型,一个代理,然后使用我的视图:

    self.modele = ModelPerso()

    self.modele.setEditStrategy(QtSql.QSqlTableModel.OnFieldChange)
    self.modele.setTable("videos")
    self.modele.select()

    self.proxy = QtGui.QSortFilterProxyModel()
    self.proxy.setSourceModel(self.modele)

    self.tableau = ViewPerso(self)
    self.tableau.setModel(self.proxy)
    self.tableau.setItemDelegate(ViewDelegate(self))

我不知道按键事件最终去了哪里,目前它们只是消失了。我觉得(我觉得),每个小部件都有处理按键事件的方法,也许 QTableView 忽略了向上和向下的按键?

2 个回答

0

对于在类外部实现的内容,你需要在外部重写这个 keyPressEvent 方法。就像这个例子:

import sys
from PyQt4 import QtCore, QtGui

class ViewPerso (QtGui.QTableView):
    def __init__(self, parent = None):
        super(ViewPerso, self).__init__(parent)
        self.parent = parent

    def currentChanged (self, current, previous):
        index = current.sibling(current.row(), 4)
        try:
            if not index.data() or len(self.parent.vidsSelected()) > 1:
                return
        except AttributeError:
            pass
        self.clicked.emit(current)
        self.scrollTo(current)

    def keyboardSearch (self, search):
        pass

class exampleQMainWindow (QtGui.QMainWindow):
    def __init__ (self):
        super(exampleQMainWindow, self).__init__()
        testQTableWidget = ViewPerso(self)
        self.setCentralWidget(testQTableWidget)
        testQTableWidget.keyPressEvent = self.keyPressEvent

    def keyPressEvent (self, eventQKeyEvent):
        key = eventQKeyEvent.key()
        if key == QtCore.Qt.Key_F1:
            print 'Help'
        elif key == QtCore.Qt.Key_F5:
            print 'Reload'
        elif key == QtCore.Qt.Key_Left:
            print 'Left'
        elif key == QtCore.Qt.Key_Up:
            print 'Up'
        elif key == QtCore.Qt.Key_Right:
            print 'Right'
        elif key == QtCore.Qt.Key_Down:
            print 'Down'

app = QtGui.QApplication([])
window = exampleQMainWindow()
window.show()
sys.exit(app.exec_())
1

好的,我最后是这样做的:

class ViewPerso (QtGui.QTableView):
    def __init__(self, parent = None):
        super(ViewPerso, self).__init__(parent)
        self.parent = parent

    def currentChanged (self, current, previous):
        index = current.sibling(current.row(), 4)
        try:
            if not index.data() or len(self.parent.vidsSelected()) > 1:
                return
        except AttributeError:
            pass
        self.clicked.emit(current)
        self.scrollTo(current)

    def keyboardSearch (self, search):
        pass

    def keyPressEvent (self, e):
        super(ViewPerso, self).keyPressEvent(e)
        e.ignore()

这个事件可能卡在了 ViewPerso 里,所以我通过重写它的 keyPressEvent 方法,像这样做,我就能得到 QTableWidget 对事件的正常处理,并且这个事件会传递给父窗口,这样我就可以再次使用它。

我试着按照你在编辑中展示的做法去做,但对我来说就是不管用,我也不知道为什么。我的程序也很大(大约 1万行),所以问题可能来自任何地方。不过谢谢你让我意识到错误的来源。

撰写回答