QTableView拦截Key_Down和Key_Up事件

问题描述 投票:0回答:3

我正在尝试在 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 和 Return 事件,它们可以工作。但不是 Key_Down 事件! Key_right 也可以工作,但 Down 则不行。我认为这是因为 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 会忽略上下按键?

python pyqt qtableview
3个回答
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 对事件所做的常规处理,并且该事件被传播到父窗口小部件,因此我可以再次使用它。

我尝试按照您在编辑中显示的内容进行操作,但它对我来说根本不起作用,我真的不知道为什么。我的程序也很大(~10k 行),所以原因可能来自任何地方。但谢谢你让我意识到错误来自哪里。


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_())

0
投票

问题和答案似乎有点混乱。如果您想将关键事件(例如)从您的

QTableView
传播到其父/祖先小部件,这通常应该有效:

def keyPressEvent(self, event):
    print(f'kpe TableView {event}')
    # super().keyPressEvent(event)
    self.parent().keyPressEvent(event)

...如果您注释掉

super()
行,则无需执行
event.ignore()
...尽管
QTableView
之外的某些组件可能会以不同的方式处理事情,特别是编辑器,我怀疑。

无论如何,接下来的事情是了解父级是什么以及其中的

KeyPressEvent
会发生什么。在我的例子中,父级是一个
QFrame
,位于
QWidget
s/
QLayout
s 的层次结构中。不过,我还在
QMainWindow
上设置了一个事件过滤器,即位于层次结构的顶部,如下所示:

class KeyPressEater(QtCore.QObject):
    def __init__(self, main_window):
        super().__init__()
        self.main_window = main_window

    def eventFilter(self, obj, event):
        if event.type() == QtCore.QEvent.KeyPress:
            key = event.key()
            if (event.modifiers() == QtCore.Qt.NoModifier):
                if key == QtCore.Qt.Key_Return:
                    self.main_window.entry_box.keyPressEvent(event)
        return super().eventFilter(obj, event)

QMainWindow
构造函数中:

self.kpe = KeyPressEater(self)
self.installEventFilter(self.kpe)

并且我确认相关事件(按下 Return 键并将焦点放在

QTableView
上)会一直传播到安装在
KeyPressEater
上的
QMainWindow
,因此被它捕获并触发按键
entry_box
上的事件由此行配置:

self.main_window.entry_box.keyPressEvent(event)
© www.soinside.com 2019 - 2024. All rights reserved.