Disabled QToolButtons inside QScrollArea prevent s

2019-07-14 05:06发布

I would like to be able to scroll with the mouse inside QScrollArea regardless if the mouse is positioned above disabled QToolButton or not. The documentation mentions disabled widgets don't propagate mouse events to parents and i figured it out i need to install event filter to overcome this issue i am experiencing. This is how far i managed to do it. I think the event filter is installed as wheel event is detected but i am not sure what should be the next steps:

from PySide import QtGui
from PySide.QtCore import *
import sys

app = QtGui.QApplication(sys.argv)

wid = QtGui.QWidget()
wid.resize(200, 200)

scroll = QtGui.QScrollArea()
scroll.setWidget(wid)

layout = QtGui.QVBoxLayout()
wid.setLayout(layout)

class installEvent(QObject):
    def eventFilter(self, i_obj, i_event):

        if i_event.type() == QEvent.Wheel:
            print "QEvent: " + str(i_event.type())


buttonEnabled = QtGui.QToolButton()
layout.addWidget(buttonEnabled)


buttonDisabled = QtGui.QToolButton()
buttonDisabled.setEnabled(False)
layout.addWidget(buttonDisabled)

buttonDisabled.installEventFilter(installEvent(buttonDisabled))

scroll.show()

sys.exit(app.exec_())

标签: qt pyside
2条回答
Anthone
2楼-- · 2019-07-14 05:47

As i guess object oriented programming style is appropriate when it comes to PySide and solving issues like this. If in the future PySide beginners stumble upon this answer here is the full example on how to make it work:

from PySide import QtGui
from PySide.QtCore import *
import sys

# http://zetcode.com/gui/pysidetutorial/firstprograms/

class Example(QtGui.QWidget):

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

        self.initUI()

    def initUI(self):

        self.scroll = QtGui.QScrollArea()
        self.scroll.setWidget(self)

        self.layout = QtGui.QVBoxLayout()
        self.setLayout(self.layout)

        self.btn = QtGui.QToolButton()
        self.btn.move(50, 50)
        self.btn.setEnabled(False)
        self.btn.installEventFilter(self)

        self.layout.addWidget(self.btn)
        self.setGeometry(300, 300, 250, 150)   
        self.scroll.show()

    def eventFilter(self, obj, event):
        if obj and not obj.isEnabled() and event.type() == QEvent.Wheel:
            newEvent = QtGui.QWheelEvent(obj.mapToParent(event.pos()), event.globalPos(),
                                   event.delta(), event.buttons(),
                                   event.modifiers(), event.orientation())
            QtGui.QApplication.instance().postEvent(obj.parent(), newEvent)
            print "QEvent: " + str(event.type())
            return True

        return QObject.eventFilter(self, obj, event) 

def main():

    app = QtGui.QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())


if __name__ == '__main__':
    main()
查看更多
看我几分像从前
3楼-- · 2019-07-14 05:50

Once you have caught the correct event, you need to post the event to the parent widget. I've done this before like this:

def eventFilter(self, obj, event):
    if obj and not obj.isEnabled() and event.type() == QEvent.Wheel:
        newEvent = QWheelEvent(obj.mapToParent(event.pos()), event.globalPos(),
                               event.delta(), event.buttons(),
                               event.modifiers(), event.orientation())
        QApplication.instance().postEvent(obj.parent(), newEvent)
        return True

    return QObject.eventFilter(self, obj, event)

This event filter only does something if the button is disabled and the event type is QEvent.Wheel. Otherwise it implements the default behaviour of eventFilter.

The login inside the if statement first maps the coordinates to the parent widget, before constructing a new QWEheelEvent with the identical parameters as the original event (except for the coordinate mapping). The final part is to grab an instance of your QApplication and use the postEvent method to send the event to the Qt event loop, where Qt will distribute the event to the appropriate widget (the parent of the disabled button).

查看更多
登录 后发表回答