DISABLE ADBLOCK

ADBlock is blocking some content on the site

ADBlock errore

Using PyQT, how do you filter mousePressEvent for a QComboBox with custom list

StackOverflow https://stackoverflow.com/questions/603528

Question

I've got a QComboBox with a custom list object.

Screenshot.

The custom list object has a custom mousePressEvent so that when the user click on one of the circles with a +/- (a twisty), the list is expanded/collapsed.

When I use the list with the combo box, when the user clicks on a twisty, the list is expanded/collapsed, but the selection is changed, and the list is hidden. How can I filter this so that when the user click on a twisty, the selection is not changed, and the list not hidden.

Additional screenshots

All of the nodes collapsed: All nodes collapsed.

List hidden: Screenshot with the list hidden.

Solution

QT has a eventFilter that "captures" QEvent.MouseButtonRelease. So what I have done is installed my own eventFilter that filters QEvent.MouseButtonRelease events if the user click on a node.

In my list object I have the following method:

def mousePressEvent (self, e):
    self.colapse_expand_click = False
    if <user clicked node>:
        colapse_expand_node()
        e.accept ()
        self.colapse_expand_click = True

The mousePressEvent runs before mouseReleaseEvent.

Then in the custom combobox, I filter the event:

class RevisionSelectorWidget(QtGui.QComboBox):
    def __init__(self, parent = None):
        QtGui.QComboBox.__init__(self, parent)

        self.log_list = RevisionSelectorLogList(self)
        self.setView(self.log_list)
        self.log_list.installEventFilter(self)
        self.log_list.viewport().installEventFilter(self)

    def eventFilter(self, object, event):
        if event.type() == QtCore.QEvent.MouseButtonRelease:
            if self.log_list.colapse_expand_click:
                return True
        return False

OTHER TIPS

Off the top of my head, you could subclass QComboBox and override hideEvent(QHideEvent) (inherited from QWidget)

def hideEvent(self, event):
  if self.OkToHide():
    event.accept()
  else:
    event.ignore()

Your screenshot looks like an interesting use of a combo box, I'm curious as to why you haven't used a TreeView style control instead of a list?

Edit (Mar 14 2009):

I looked at the Qt source code and it looks like when the keyboard and mouse events are captured, that as soon as qt has decided to emit the "activated(int index)" signal, "hidePopup()" has been called.

So apart from rewriting their event filter code, another option is to connect the "activated(int index)" or "highlighted(int index)" signal to a slot that can call "showPopup()" which would re-raise the list items. If you get a nasty disappear/appear paint issue you may have to get Qt to delay the paint events while the popup is visible.

Hope that helps!

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow