Python PyQt:在基类中跳过“mousePressEvent”方法时,将“mousePressEvent”传递给原始小部件

Python PyQt:在基类中跳过“mousePressEvent”方法时,将“mousePressEvent”传递给原始小部件,python,pyqt,pyqt5,Python,Pyqt,Pyqt5,我正在尝试为小部件创建一个全局上下文帮助系统。其中,可以使用ContextHelpBase类扩展所有小部件,并具有向上下文帮助显示小部件发送信号所需的所有逻辑 这个想法是,当用户点击一个小部件时,它会显示一些上下文帮助。因此,我重载了mousePressEvent以发送信号,但现在正常按钮和QComboBox行为不起作用,因为我假设在重写正常事件处理程序后,我没有在正常事件处理程序上传递信号 from PyQt5.QtWidgets import QApplication, QLabel, QW

我正在尝试为小部件创建一个全局上下文帮助系统。其中,可以使用ContextHelpBase类扩展所有小部件,并具有向上下文帮助显示小部件发送信号所需的所有逻辑

这个想法是,当用户点击一个小部件时,它会显示一些上下文帮助。因此,我重载了
mousePressEvent
以发送信号,但现在正常按钮和QComboBox行为不起作用,因为我假设在重写正常事件处理程序后,我没有在正常事件处理程序上传递信号

from PyQt5.QtWidgets import QApplication, QLabel, QWidget, QPushButton, QComboBox, QHBoxLayout, QVBoxLayout
from PyQt5.QtCore import QObject, pyqtSignal, pyqtSlot

class ContextHelpSignals(QObject):
    """ Used to send signals globally through the application
        Eventually will be a Global Singelton
    """
    textHelp = pyqtSignal(str)

    def __init__(self):
        super(ContextHelpSignals, self).__init__()

#Eventually will be a Global Singleton
_contextHelp = ContextHelpSignals()

class ContextHelpBaseClass(QObject):
    """All Widget that have context help inherits this class"""
    def __init__(self, **kw):
        super(ContextHelpBaseClass, self).__init__()
        self.helpText = None

    def mousePressEvent(self, event):
        """ THIS DISABLE WIDGETS NORMAL CLICK BEHAVIOR """
        _contextHelp.textHelp.emit(self.helpText)
        # How can emit a signal and then pass this event to the normal widget
        print(type(super()))

    def SetHelpText(self, helpText):
        self.helpText = helpText

class ContexHelpDisplay(QLabel):
    """Dislpay Context Help frow widgets that have Context Help"""
    def __init__(self, text):
        super(ContexHelpDisplay, self).__init__()
        self.setText(text)
        _contextHelp.textHelp.connect(self.__displayHelp)
        # Need to pass event to original widget
        # type.mousePresseEvent() - How do I get type?

    @pyqtSlot(str)
    def __displayHelp(self, contextHelpText):
        self.setText(contextHelpText)

class ContextHelpButton(QPushButton, ContextHelpBaseClass):
    """QPush Button with Context Help"""
    def __init__(self, text):
        super(ContextHelpButton, self).__init__()
        self.setText(text)
        self.helpText = "This is QPushButton Context Help Text"

## It would be nice if I could use a Python Decorator, but
## don't know how yet.
## @ContextHelp
class ContextHelpComboBox(QComboBox, ContextHelpBaseClass):
    """QPush Button with Context Help"""
    def __init__(self):
        super(ContextHelpComboBox, self).__init__()
        self.helpText = "This is QComboBox Context Help Text"

class MainWindow(QWidget):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent=parent)
        self.setupUI()

    def setupUI(self):
        self.resize(250, 150)
        self.setWindowTitle('Context Help Example')
        self.show()

        button = ContextHelpButton("Test Button")

        comboBox = ContextHelpComboBox()
        comboBox.addItem("Test Item 1")
        comboBox.addItem("Test Item 2")
        comboBox.addItem("Test Item 3")

        helpTextDisplay = ContexHelpDisplay("Context Help")

        vBox = QVBoxLayout()
        vBox.addWidget(button)
        vBox.addWidget(comboBox)

        hBox = QHBoxLayout()
        hBox.addLayout(vBox)
        hBox.addWidget(helpTextDisplay)

        self.setLayout(hBox)

if __name__ == "__main__":
    app = QApplication([])
    ex = MainWindow()
    exit(app.exec_())
主要问题

如何将鼠标按下事件传递给原始小部件

其他问题

  • 使用Python装饰器可以做到这一点吗
  • 是否有更好的设计模式更适合这种情况

  • @eyllanesc对它的描述可以是这样的:

    from PyQt5.QtWidgets import (QApplication, QLabel, QWidget, QPushButton, 
                                 QComboBox, QHBoxLayout, QVBoxLayout)
    from PyQt5.QtCore    import QObject, pyqtSignal, pyqtSlot,  QEvent, Qt
    
    
    class ContextHelpSignals(QObject):
        """ Used to send signals globally through the application
            Eventually will be a Global Singelton                """
        textHelp = pyqtSignal(str)
    
        def __init__(self):
            super(ContextHelpSignals, self).__init__()
    
    
    # Eventually will be a Global Singleton
    _contextHelp = ContextHelpSignals()
    
    
    class ContextHelpBaseClass(QObject):   
        """ All Widget that have context help inherits this class """
        def __init__(self, **kw):
            super(ContextHelpBaseClass, self).__init__()
            self.helpText = None
    
        def mousePressEvent(self, event):
            ''' THIS DISABLE WIDGETS NORMAL CLICK BEHAVIOR '''
            _contextHelp.textHelp.emit(self.helpText)
            # How can emit a signal and then pass this event to the normal widget
            print(type(super()))
    
        def SetHelpText(self, helpText):              # ???
            self.helpText = helpText
    
    
    class ContexHelpDisplay(QLabel):
        """Dislpay Context Help frow widgets that have Context Help"""
        def __init__(self, text):
            super(ContexHelpDisplay, self).__init__()
            self.setText(text)
            _contextHelp.textHelp.connect(self.__displayHelp)
            # Need to pass event to original widget
            # type.mousePresseEvent() - How do I get type?
    
        @pyqtSlot(str)
        def __displayHelp(self, contextHelpText):
            self.setText(contextHelpText)
    
    class ContextHelpButton(QPushButton, ContextHelpBaseClass):
        """QPush Button with Context Help"""
        def __init__(self, text):
            super(ContextHelpButton, self).__init__()
            self.setText(text)
            self.helpText = "This is <b>QPushButton</b> Context Help Text"
    
    
    class ContextHelpComboBox(QComboBox):             # - --> , ContextHelpBaseClass):
        """QPush Button with Context Help"""
        def __init__(self):
            super(ContextHelpComboBox, self).__init__()
            self.helpText = "This is <b>QComboBox</b> Context Help Text"
    
    
    class MainWindow(QWidget):
        def __init__(self, parent=None):
            super(MainWindow, self).__init__(parent=parent)
            self.setupUI()
    
        def setupUI(self):
            self.resize(250, 150)
            self.setWindowTitle('Context Help Example')
            self.show()
    
            button = ContextHelpButton("Test Button")
    
            self.comboBox = ContextHelpComboBox()     # + self.
            self.comboBox.addItem("Test Item 1")
            self.comboBox.addItem("Test Item 2")
            self.comboBox.addItem("Test Item 3")
    
            self.comboBox.installEventFilter(self)    # <- Installs an event filter filterObj on this object. 
    
            self.helpTextDisplay = ContexHelpDisplay("Context Help")
    
            vBox = QVBoxLayout()
            vBox.addWidget(button)
            vBox.addWidget(self.comboBox)
    
            hBox = QHBoxLayout()
            hBox.addLayout(vBox)
            hBox.addWidget(self.helpTextDisplay)
            self.setLayout(hBox)
    
        # Filters events if this object has been installed as an event filter for the watched object.
        def eventFilter(self, obj, event):
            if event.type() == QEvent.MouseButtonPress and obj is self.comboBox:
                self.helpTextDisplay.setText(self.comboBox.helpText)
            return super(MainWindow, self).eventFilter(obj, event)
    
    
    if __name__ == "__main__":
        app = QApplication([])
        ex  = MainWindow()
        exit(app.exec_())
    
    从PyQt5.qtwidts导入(QApplication、QLabel、QWidget、QPushButton、,
    QComboBox、QHBoxLayout、QVBoxLayout)
    从PyQt5.QtCore导入QObject、pyqtSignal、pyqtlot、QEvent、Qt
    类上下文帮助信号(QObject):
    “”“用于通过应用程序全局发送信号
    最终将成为一名全球歌手
    textHelp=pyqtSignal(str)
    定义初始化(自):
    super(ContextHelpSignals,self)。\uuuu init\uuuuu()
    #最终将成为全球单身汉
    _contextHelp=ContextHelpSignals()
    类ContextHelpBaseClass(QObject):
    “”“所有具有上下文帮助的小部件都继承此类”“”
    def初始功率(自身功率,**kw):
    super(ContextHelpBaseClass,self)。\uuuu init\uuuu()
    self.helpText=None
    def鼠标压力事件(自身、事件):
    ''这将禁用小部件的正常单击行为''
    _contextHelp.textHelp.emit(self.helpText)
    #如何发出信号,然后将此事件传递给普通小部件
    打印(键入(super())
    def SetHelpText(self,helpText):#???
    self.helpText=helpText
    类ContexHelpDisplay(QLabel):
    “”“为具有上下文帮助的小部件显示上下文帮助”“”
    定义初始化(self,text):
    super(ContexHelpDisplay,self)。\uuuu init\uuuuu()
    self.setText(文本)
    _contextHelp.textHelp.connect(self.\u显示帮助)
    #需要将事件传递给原始小部件
    #type.mousePresseEvent()-如何获取类型?
    @pyqtSlot(str)
    def_u_显示帮助(self、contextHelpText):
    self.setText(contextHelpText)
    类ContextHelpButton(QPushButton,ContextHelpBaseClass):
    “”“带上下文帮助的QPush按钮”“”
    定义初始化(self,text):
    super(ContextHelpButton,self)。\uuuuu init\uuuuuu()
    self.setText(文本)
    self.helpText=“这是QPushButton上下文帮助文本”
    类ContextHelpComboBox(QComboBox):#--->,ContextHelpBaseClass):
    “”“带上下文帮助的QPush按钮”“”
    定义初始化(自):
    超级(ContextHelpComboBox,self)。\uuuu init
    self.helpText=“这是QComboBox上下文帮助文本”
    类主窗口(QWidget):
    def uuu init uuu(self,parent=None):
    超级(主窗口,自我)。\uuuuu初始化\uuuuuuuuuuuuuu(父级=父级)
    self.setupUI()
    def设置UI(自):
    自我调整大小(250150)
    self.setWindowTitle('上下文帮助示例')
    self.show()
    按钮=上下文帮助按钮(“测试按钮”)
    self.comboBox=ContextHelpComboBox()#+self。
    self.comboBox.addItem(“测试项1”)
    self.comboBox.addItem(“测试项2”)
    self.comboBox.addItem(“测试项目3”)
    
    self.comboBox.installEventFilter(self)#作为后续操作,我通过在基类中存储子类的引用,然后使用该引用传递事件来实现我想要的

    from PyQt5.QtWidgets import (QApplication, QLabel, QWidget, QPushButton,
                                 QComboBox, QHBoxLayout, QVBoxLayout)
    from PyQt5.QtCore    import QObject, pyqtSignal, pyqtSlot
    
    class ContextHelpSignals(QObject):
        """ Used to send signals globally through the application
            Eventually will be a Global Singleton                """
        textHelp = pyqtSignal(str)
    
        def __init__(self):
            super(ContextHelpSignals, self).__init__()
    
    # Eventually will be a Global Singleton
    _contextHelp = ContextHelpSignals()
    
    class ContexHelpDisplay(QLabel):
        """Display Context Help from widgets that have Context Help"""
        def __init__(self, text):
            super(ContexHelpDisplay, self).__init__()
            self.setText(text)
            _contextHelp.textHelp.connect(self.__displayHelp)
    
        @pyqtSlot(str)
        def __displayHelp(self, contextHelpText):
            self.setText(contextHelpText)
    
    class ContextHelpBaseClass(QObject):
        """ All Widget that have context help inherits this class """
        def __init__(self, childObject):
            super(ContextHelpBaseClass, self).__init__()
            self.helpText = None
            self.childObject = childObject
            print( type(childObject) )
    
        def mousePressEvent(self, event):
            _contextHelp.textHelp.emit(self.helpText)
            # Pass mouse click event to native widget
            self.childObject.mousePressEvent(event)
    
    class ContextHelpButton(QPushButton, ContextHelpBaseClass):
        """QPush Button with Context Help"""
        def __init__(self, text):
            super(ContextHelpButton, self).__init__(self)
            self.setText(text)
            self.helpText = "This is <b>QPushButton</b> Context Help Text"
    
        def test(self):
            print("BUTTON")
    
    class ContextHelpComboBox(QComboBox, ContextHelpBaseClass):
        """QPush Button with Context Help"""
        def __init__(self):
            super(ContextHelpComboBox, self).__init__(self)
            self.helpText = "This is <b>QComboBox</b> Context Help Text"
    
        def test(self):
            print("Combo Box")
    
    class MainWindow(QWidget):
        def __init__(self, parent=None):
            super(MainWindow, self).__init__(parent=parent)
            self.setupUI()
    
        def setupUI(self):
            self.resize(250, 150)
            self.setWindowTitle('Context Help Example')
            self.show()
    
            button = ContextHelpButton("Test Button")
    
            comboBox = ContextHelpComboBox()
            comboBox.addItem("Test Item 1")
            comboBox.addItem("Test Item 2")
            comboBox.addItem("Test Item 3")
    
            helpTextDisplay = ContexHelpDisplay("Context Help")
    
            button.clicked.connect(button.test)
    
            vBox = QVBoxLayout()
            vBox.addWidget(button)
            vBox.addWidget(comboBox)
    
            hBox = QHBoxLayout()
            hBox.addLayout(vBox)
            hBox.addWidget(helpTextDisplay)
            self.setLayout(hBox)
    
    if __name__ == "__main__":
        app = QApplication([])
        ex  = MainWindow()
        exit(app.exec_())
    
    从PyQt5.qtwidts导入(QApplication、QLabel、QWidget、QPushButton、,
    QComboBox、QHBoxLayout、QVBoxLayout)
    从PyQt5.QtCore导入QObject、pyqtSignal、pyqtSlot
    类上下文帮助信号(QObject):
    “”“用于通过应用程序全局发送信号
    最终将成为全球单身人士
    textHelp=pyqtSignal(str)
    定义初始化(自):
    super(ContextHelpSignals,self)。\uuuu init\uuuuu()
    #最终将成为全球单身汉
    _contextHelp=ContextHelpSignals()
    类ContexHelpDisplay(QLabel):
    “”“从具有上下文帮助的小部件显示上下文帮助”“”
    定义初始化(self,text):
    super(ContexHelpDisplay,self)。\uuuu init\uuuuu()
    self.setText(文本)
    _contextHelp.textHelp.connect(self.\u显示帮助)
    @pyqtSlot(str)
    def_u_显示帮助(self、contextHelpText):
    self.setText(contextHelpText)
    类ContextHelpBaseClass(QObject):
    “”“所有具有上下文帮助的小部件都继承此类”“”
    定义初始化(self,childObject):
    super(ContextHelpBaseClass,self)。\uuuu init\uuuu()
    self.helpText=None
    self.childObject=childObject
    打印(类型(子对象))
    def鼠标压力事件(自身、事件):
    _contextHelp.textHelp.emit(self.helpText)
    #将鼠标单击事件传递给本机小部件
    self.childObject.mousePressEvent(事件)
    类ContextHelpButton(QPushButton,ContextHelpBaseClass):
    “”“带上下文帮助的QPush按钮”“”
    定义初始化(self,text):
    super(ContextHelpButton,self)。\uuuu init\uuuu(self)
    self.setText(文本)
    self.helpText=“这是QPushButton上下文帮助文本”
    def测试(自我):
    打印(“按钮”)
    类ContextHelpComboBox(QComboBox,ContextHelpBaseClass):
    “”“带上下文帮助的QPush按钮”“”
    定义初始化(自):
    超级(ContextHelpComboBox,self)。\uuuu init\uuuuu(self)
    self.helpText=“这是QComboBox上下文帮助文本”
    def测试(自我):
    打印(“组合框”)
    类主窗口(QWidget):
    def uuu init uuu(self,parent=None):
    超级(主窗口,自我)。\uuuuu初始化\uuuuuuuuuuuuuu(父级=父级)
    self.setupUI()
    def设置
    
    from PyQt5.QtWidgets import (QApplication, QLabel, QWidget, QPushButton,
                                 QComboBox, QHBoxLayout, QVBoxLayout)
    from PyQt5.QtCore    import QObject, pyqtSignal, pyqtSlot
    
    def ContextHelp(text):
        """Decorates a class by adding mousePressEvent method"""
        def AddMouseClickEventDecorator(_class):
            """ Adds 'mousePressEvent()' method to class"""
            def mousePressEvent(self, event):
                _contextHelp.textHelp.emit(text)       #Emit a signal to global ContextHelp Singleton
                super(_class, self).mousePressEvent(event) #Call Widget Base Class event
    
            #Add 'mousePressEvent' to _class
            setattr(_class, 'mousePressEvent', mousePressEvent)
            return _class #Decorated class
        return AddMouseClickEventDecorator
    
    
    
    class ContextHelpSignals(QObject):
        """ Used to send signals globally through the application
            Eventually will be a Global Singleton                """
        textHelp = pyqtSignal(str)
    
        def __init__(self):
            super(ContextHelpSignals, self).__init__()
    
    # Eventually will be a Global Singleton
    _contextHelp = ContextHelpSignals()
    
    class ContexHelpDisplay(QLabel):
        """Display Context Help from widgets that have Context Help"""
        def __init__(self, text):
            super(ContexHelpDisplay, self).__init__()
            self.setText(text)
            _contextHelp.textHelp.connect(self.__displayHelp)
    
        @pyqtSlot(str)
        def __displayHelp(self, contextHelpText):
            self.setText(contextHelpText)
    
    @ContextHelp("This is a push button")
    class ContextHelpButton(QPushButton):
        """QPush Button with Context Help"""
        def __init__(self, text):
            super(ContextHelpButton, self).__init__()
            self.setText(text)
    
    @ContextHelp("This is Combo Box")
    class ContextHelpComboBox(QComboBox):
        """QPush Button with Context Help"""
        def __init__(self):
            super(ContextHelpComboBox, self).__init__()
    
    
    class MainWindow(QWidget):
        def __init__(self, parent=None):
            super(MainWindow, self).__init__(parent=parent)
            self.setupUI()
    
        def setupUI(self):
            self.resize(250, 150)
            self.setWindowTitle('Context Help Example')
            self.show()
    
            button = ContextHelpButton("Test Button")
    
            comboBox = ContextHelpComboBox()
            comboBox.addItem("Test Item 1")
            comboBox.addItem("Test Item 2")
            comboBox.addItem("Test Item 3")
    
            helpTextDisplay = ContexHelpDisplay("Context Help")
    
            button.clicked.connect(self.TestButton)
    
            vBox = QVBoxLayout()
            vBox.addWidget(button)
            vBox.addWidget(comboBox)
    
            hBox = QHBoxLayout()
            hBox.addLayout(vBox)
            hBox.addWidget(helpTextDisplay)
            self.setLayout(hBox)
    
        def TestButton(self):
            print("Button Pressed.")
    
    if __name__ == "__main__":
        app = QApplication([])
        ex  = MainWindow()
        exit(app.exec_())