【问题标题】:Can QWidget detect mouse events on behalf of a QLineEdit?QWidget 可以代表 QLineEdit 检测鼠标事件吗?
【发布时间】:2012-11-08 01:19:46
【问题描述】:

我有一个 QWidget,它并排包含 QLabels 和 QLineEdits。

当我点击一个 QLabel 时,我可以在 QWidget 中使用 mousePressEvent。但是当我单击 QLineEdit 时,我无法在 QWidget 中检测到 mousePressEvent - 仅在 QLineEdit 中。我认为这与 QLineEdit 的工作方式有关 - 我不知道在整个区域内获取鼠标事件的方法。

编辑

我已经为 Maya 制作了一个自定义频道框,如上所示。我尝试通过拖动鼠标来选择多个通道。但正如我所提到的,在 QLineEdit 区域我不能这样做。

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())

每个元素由一个 QLabel 和一个 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)

包含小部件的工作方式如上。当我点击 QLabel 区域时,我可以得到鼠标事件,但是当我点击 QLineEdit 区域时,我不能。

【问题讨论】:

  • 问题不清楚,你试过SIGNALS和SLOTS吗?
  • @AmazingSixty 是的,我尝试使用 SIGNAL 和 SLOT 方法。但是,它在mouseMoveEvent() 上无法正常工作:(
  • 让我明白这一点吗?当用户点击 QLineEdit 时,您希望发生什么事情吗?
  • 将代码粘贴到您的问题中,方便我们理解
  • 无耻插件:如果您最终想了解有关此过程的更多详细信息,我实际上在我的 PyQt for Maya video tutorial 中创建了一个 Maya ChannelBox :-)

标签: pyqt mouseevent qlineedit


【解决方案1】:

如果您从包含布局的主窗口小部件观看mousePressEvent(),您看到点击QLabel 的原因是因为默认情况下QLabel 会忽略mousePressEvent 并允许它冒泡下一位家长。事件从 child->parent 向上传播。

然而,QLineEdit 确实需要接受并使用鼠标按下,以处理线编辑小部件常见的焦点和其他各种操作。

所以对于您来说,真正的好选择是使用event filter。这将允许您的主小部件监视其他小部件的事件,而无需继承 QLineEdit 并实现 mousePressEvent

在此示例中,它只是监视布局的任何成员和鼠标按下,然后打印,然后执行默认操作以不更改任何内容:

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)

当您测试此代码时,您会看到单击标签会导致主小部件及其事件过滤器中的打印。但是单击行编辑只会导致事件过滤器打印语句,因为默认的mousePressEvent 接受它并且不会进一步传播它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-19
    相关资源
    最近更新 更多