3

I have a QWidget that contains QLabels and QLineEdits side by side.

When I click on a QLabel, I can use the mousePressEvent in QWidget. But when I click on QLineEdit, I can't detect the mousePressEvent in QWidget - only in the QLineEdit. I think that it is related to how QLineEdit works - I don't know the way to get mouse events within the whole region.

EDIT:

enter image description here

I have made a custom channel box for Maya like above. I try to select multiple channels by dragging the mouse. But as I mentioned, in the QLineEdit regions I can't do this.

class channelWidget(QtGui.QWidget):
  def __init__(self, parent=None):
    super(channelWidget, self).__init__(parent)
    self.resize(180, 20)        
    self.setMinimumSize(180, 20)
    self.setMaximumHeight(20)
    self.attr_label = QtGui.QLabel(self)
    self.attr_label.setGeometry(QtCore.QRect(5, 0, 110, 20))
    self.attr_label.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
    self.value_field = focusLineEdit(self)
    self.value_field.setGeometry(QtCore.QRect(120, 0, 60, 20))
    self.value_field.setAlignment(QtCore.Qt.AlignLeft|QtCore.Qt.AlignLeading|QtCore.Qt.AlignVCenter)
    self.value_field.setValidator(QtGui.QDoubleValidator())

Each element consists of a QLabel and a QLineEdit.

class channelContainerWidget(QtGui.QWidget):
  def updateChannel(self, node="", attrList=[]):
    _l = self.channel_layout
    _list = []
    for w in [_l.itemAt(i).widget() for i in range(_l.count()) if _l.itemAt(i).widget()]:
      if w in self._selectList: _list.append( str( w.attr_label.text() ) )
        sip.delete(w)

    _selList = []
    for _id, at in enumerate(attrList):
      _item = channelWidget(self)
      _item.attr_label.setText(at)
      _item.value_field.setText(value)
      _l.insertWidget(_id, _item)

And the containing widget works as above. When I click on QLabel region, I can get mouse events, but when I click on the QLineEdit region, I can't.

ekhumoro
  • 115,249
  • 20
  • 229
  • 336
Hyun-geun Kim
  • 919
  • 3
  • 22
  • 37
  • question is not clear, have you tried SIGNALS and SLOTS ? – warunanc Nov 20 '12 at 04:10
  • @AmazingSixty Yes, I tried with SIGNAL and SLOT method. But, it doesn't work as I wish on `mouseMoveEvent()` :( – Hyun-geun Kim Nov 20 '12 at 05:32
  • Let me get this straight ? Do you want something to happen when a user clicks on the QLineEdit ? – warunanc Nov 20 '12 at 08:59
  • Paste the code in your question, so it would be easy for us to understand – warunanc Nov 20 '12 at 09:02
  • Shameless plug: In case you end up wanting more detailed information on this process, I actually create a Maya ChannelBox in my [PyQt for Maya video tutorial](http://www.cmivfx.com/tutorials/view/498/PyQt4+UI+Development+for+Maya) :-) – jdi Dec 14 '12 at 02:02
  • Also, why use `sip.delete(w)` instead of `w.deleteLater()`? – jdi Dec 14 '12 at 02:28

1 Answers1

3

If you are watching the mousePressEvent() from the main widget containing the layout, the reason you are seeing clicks for the QLabel is because by default a QLabel ignores the mousePressEvent and allows it to bubble up to the next parent. Events propagate upward from child->parent.

A QLineEdit however does need to accept and use a mouse press, to handle focus and other various actions common to a line edit widget.

So really what might be a good option for you is to use an event filter. This will allow your main widget to watch events for other widgets, without having to subclass the QLineEdit and implement the mousePressEvent

In this example, it simply watches for any member of the layout and a mouse press, and prints, then does the default action to not change anything:

class Widget(QtGui.QWidget):

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

        self.layout = QtGui.QHBoxLayout(self)

        self.label = QtGui.QLabel("Label")
        self.line = QtGui.QLineEdit()

        self.layout.addWidget(self.label)
        self.layout.addWidget(self.line)        

        # have this widget (self) watch events for these    
        self.label.installEventFilter(self)
        self.line.installEventFilter(self)

    def mousePressEvent(self, event):
        print "Main Widget Mouse Press"
        super(Widget, self).mousePressEvent(event)

    def eventFilter(self, obj, event):
        # you could be doing different groups of actions
        # for different types of widgets and either filtering
        # the event or not.
        # Here we just check if its one of the layout widgets
        if self.layout.indexOf(obj) != -1:
            if event.type() == event.MouseButtonPress:
                print "Widget click", obj
                # if I returned True right here, the event
                # would be filtered and not reach the obj,
                # meaning that I decided to handle it myself

        # regardless, just do the default
        return super(Widget, self).eventFilter(obj, event)

When you test this code, you will see that clicking the label causes both a print in the main widget and its event filter. But clicking on the line edit causes only the event filter print statement, because the default mousePressEvent accepts it and does not propagate it further.

jdi
  • 90,542
  • 19
  • 167
  • 203