创建事件过滤器

发布于 2024-09-11 02:51:47 字数 610 浏览 4 评论 0原文

我正在尝试在树视图中启用删除键。这就是我到目前为止所拥有的:

class delkeyFilter(QObject):
    delkeyPressed = pyqtSignal()

    def eventFilter(self,  obj,  event):
        if event.type() == QEvent.KeyPress:
            if event.key() == Qt.Key_Delete:
                self.delkeyPressed.emit()
                print 'delkey pressed'
                return True
        return False

我像这样连接eventfilter

    filter = delkeyFilter(self.dataTreeView)
    self.dataTreeView.installEventFilter(filter)

为什么在创建过滤器时需要传递self.dataTreeview?没有它它就无法工作。

I am trying to enable the delete key in my treeview. This is what I have so far:

class delkeyFilter(QObject):
    delkeyPressed = pyqtSignal()

    def eventFilter(self,  obj,  event):
        if event.type() == QEvent.KeyPress:
            if event.key() == Qt.Key_Delete:
                self.delkeyPressed.emit()
                print 'delkey pressed'
                return True
        return False

I connect the eventfilter like this:

    filter = delkeyFilter(self.dataTreeView)
    self.dataTreeView.installEventFilter(filter)

Why do I need to pass self.dataTreeview when I create the filter? It doesn't work without it.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

初相遇 2024-09-18 02:51:47

@balpha是正确的。简单的答案是,如果您不传入父级或以其他方式确保 filter 实例具有实时引用,它将被垃圾收集。

PyQt 使用 SIP 绑定到 Qt 的 C++ 实现。来自 SIP 文档

当 C++ 实例被包装时,就会创建相应的 Python 对象。 Python 对象的行为正如您所期望的垃圾回收一样——当它的引用计数达到零时,它就会被垃圾回收。那么相应的 C++ 实例会发生什么呢?明显的答案可能是调用实例的析构函数。然而,库 API 可能会说,当实例被传递给特定函数时,库获得实例的所有权,即调用实例析构函数的责任从 SIP 生成的模块转移到库。

一个实例的所有权也可能与另一个实例相关联。这意味着如果拥有的实例被销毁,则拥有的实例将自动被销毁。 SIP 跟踪这些关系,以确保 Python 的循环垃圾收集器可以检测并中断拥有实例和被拥有实例之间的任何引用循环。该关联是作为拥有实例引用所拥有实例来实现的。

上面的内容意味着,如果您将 Python 对象传递给拥有所有权的 Qt 对象,则一切都会正常工作,即使您无法保证维护对特定对象的引用。

因此,为了重申 @balpha 在他的评论中所说的话,当您不想将对象传递给构造函数时,这里有一种解决方法:

self.filter = delkeyFilter()
self.dataTreeView.installEventFilter(self.filter)

@balpha is correct. The simple answer is that if you don't pass in a parent or otherwise ensure that the filter instance has a live reference, it will be garbage collected.

PyQt uses SIP to bind to Qt's C++ implementation. From the SIP documentation:

When a C++ instance is wrapped a corresponding Python object is created. The Python object behaves as you would expect in regard to garbage collection - it is garbage collected when its reference count reaches zero. What then happens to the corresponding C++ instance? The obvious answer might be that the instance’s destructor is called. However the library API may say that when the instance is passed to a particular function, the library takes ownership of the instance, i.e. responsibility for calling the instance’s destructor is transferred from the SIP generated module to the library.

Ownership of an instance may also be associated with another instance. The implication being that the owned instance will automatically be destroyed if the owning instance is destroyed. SIP keeps track of these relationships to ensure that Python’s cyclic garbage collector can detect and break any reference cycles between the owning and owned instances. The association is implemented as the owning instance taking a reference to the owned instance.

The above implies that if you pass a Python object to a Qt object that takes ownership, everything will also work, even though you haven't guaranteed that a reference to the specific object was maintained.

So, to restate what @balpha said in his comment, here's one workaround for the case when you don't want to pass in an object to the constructor:

self.filter = delkeyFilter()
self.dataTreeView.installEventFilter(self.filter)
呆° 2024-09-18 02:51:47

QAbstractItemView 中已经实现了密钥处理。您所要做的就是对树视图进行子类化,然后实现keyPressEvent

class MyTreeView(QTreeView):

    delkeyPressed = pyqtSignal()

    def __init__(self):
        QTreeView.__init__(self)

    def keyPressEvent(self, event): #QKeyEvent
        if event.key() == Qt.Key_Delete:
            self.delkeyPressed.emit()
            print 'del key pressed'

        # pass the event up the chain or we will eat the event
        QTreeView.keyPressEvent(self, event)

`

Key handling is already implimented in QAbstractItemView. All you have to do is subclass the treeview, then implement keyPressEvent.

class MyTreeView(QTreeView):

    delkeyPressed = pyqtSignal()

    def __init__(self):
        QTreeView.__init__(self)

    def keyPressEvent(self, event): #QKeyEvent
        if event.key() == Qt.Key_Delete:
            self.delkeyPressed.emit()
            print 'del key pressed'

        # pass the event up the chain or we will eat the event
        QTreeView.keyPressEvent(self, event)

`

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文