覆盖 Qt MouseEvent 但仅当类变量为 True 时

Posted

技术标签:

【中文标题】覆盖 Qt MouseEvent 但仅当类变量为 True 时【英文标题】:Override a Qt MouseEvent but only if class variable is True 【发布时间】:2019-07-29 02:54:53 【问题描述】:

我有QComboBox,我希望用户能够锁定其索引。为此,我将QComboBox 子类化并将mousePressEvent 覆盖为空,但在QComboBox 的方法中。

我尝试的两个问题:

我不知道如何在另一个类方法中重新定义mousePressEvent 如果不满足某个条件,我不知道如何恢复QComboBox 的原始mousePressEvent 行为。我的代码:
class MyComboBox(QtWidgets.QComboBox):
    def __init__(self, *args, **kwargs):
        super(self.__class__, self).__init__(*args, **kwargs)

    def lockSelection(self, bool=None):
        if bool:
            def mousePressEvent(self, *args, **kwargs):
                pass
        else:
            def mousePressEvent(self, *args, **kwargs):
                return QtWidgets.QComboBox.mousePressEvent(*args, **kwargs)

..... later

## I want this to get my overriden mousePressEvent 

MyComboBox.lockSelection(True)

## I want this to get the original mousePressEvent

MyComboBox.lockSelection(False)

【问题讨论】:

【参考方案1】:

如果你想阻止一个继承的方法,你只需要重写该方法并避免在必要时调用该方法:

from PyQt5 import QtWidgets


class MyComboBox(QtWidgets.QComboBox):
    def lockSelection(self, lock):
        self._lock_selection = lock

    def mousePressEvent(self, event):
        lock = getattr(self, "_lock_selection", False)
        if not lock:
            super(MyComboBox, self).mousePressEvent(event)


if __name__ == "__main__":
    import sys

    app = QtWidgets.QApplication(sys.argv)

    w = QtWidgets.QWidget()

    combo = MyComboBox()
    combo.addItems(list("ABCD"))

    radio = QtWidgets.QCheckBox("Lock")
    radio.toggled.connect(combo.lockSelection)

    lay = QtWidgets.QHBoxLayout(w)
    lay.addWidget(radio)
    lay.addWidget(combo)
    w.resize(320, 60)
    w.show()
    sys.exit(app.exec_())

如果你想避免继承,你可以使用事件过滤器实现一个储物柜,这样你就可以在任何小部件中使用它:

from PyQt5 import QtCore, QtWidgets


class MouseLocker(QtCore.QObject):
    def __init__(self, widget):
        super(MouseLocker, self).__init__(widget)
        widget.installEventFilter(self)
        self._lock_selection = False

    def lockSelection(self, lock):
        self._lock_selection = lock

    def eventFilter(self, obj, event):
        if obj is self.parent() and event.type() == QtCore.QEvent.MouseButtonPress:
            return self._lock_selection
        return super(MouseLocker, self).eventFilter(obj, event)


if __name__ == "__main__":
    import sys

    app = QtWidgets.QApplication(sys.argv)

    w = QtWidgets.QWidget()

    combo = QtWidgets.QComboBox()
    combo.addItems(list("ABCD"))
    locker = MouseLocker(combo)

    radio = QtWidgets.QCheckBox("Lock")
    radio.toggled.connect(locker.lockSelection)

    lay = QtWidgets.QHBoxLayout(w)
    lay.addWidget(radio)
    lay.addWidget(combo)
    w.resize(320, 60)
    w.show()
    sys.exit(app.exec_())

【讨论】:

第一个对我来说就像一个魅力!我也尝试使用事件过滤器方法并且它有效,但是由于某种原因,当鼠标离开 UI 窗口时,ComboBox 小部件消失了。有点奇怪。

以上是关于覆盖 Qt MouseEvent 但仅当类变量为 True 时的主要内容,如果未能解决你的问题,请参考以下文章

viewForHeaderInSection 绘制背景但仅当视图位于屏幕顶部时

Apache Tiles 失败并出现错误,但仅当日志级别设置大于 INFO 时?

如何在 SQL 中选择最接近的值,但仅当该值较大时?

如何在没有 MouseEvent 的情况下检测 Qt 中的鼠标状态

在字符串中查找子字符串,但仅当整个单词?

R - 如何在NA中填写值,但仅当结束值与起始值相同时?