QComboBox 点击触发主 QDialog 上的 leaveEvent

Posted

技术标签:

【中文标题】QComboBox 点击触发主 QDialog 上的 leaveEvent【英文标题】:QComboBox click triggers a leaveEvent on the main QDialog 【发布时间】:2020-04-27 20:03:09 【问题描述】:

我正在尝试构建一个悬停对话框,但我陷入了 QComboBox 选择和 QDialog 的 leaveEvent 之间的交互。看起来当我尝试单击组合框以选择某些内容时,它触发了一个 leaveEvent,然后隐藏了我的 QDialog。为什么会这样?当我将鼠标移到对话框之外时,我可以尝试确保仅隐藏对话框?

from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
import sys

class hoverDialog(QDialog):

    def __init__(self, parent=None):
        super().__init__()
        self.setAttribute(Qt.WA_DeleteOnClose)
        self.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint)
        self.v = QVBoxLayout()
        self.combobox = QComboBox()
        self.combobox.addItems(['Work-around','Permanent'])
        self.textedit = QPlainTextEdit()
        self.v.addWidget(self.combobox)
        self.v.addWidget(self.textedit)
        self.setLayout(self.v)
        #self.setMouseTracking(True)

    def leaveEvent(self, event):
        self.hide()
        return super().leaveEvent(event)

class Table(QWidget):

    def __init__(self, parent=None):
        super().__init__()

        self.label4 = QLabel()
        self.label4.setText("hover popup")
        self.label4.installEventFilter(self)
        self.checkbox1 = QCheckBox()

        self.pushButton3 = QPushButton()
        self.pushButton3.setText('Generate')
        self.pushButton3.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Preferred)
        self.pushButton3.clicked.connect(self.buttonPressed)

        self.hbox5 = QHBoxLayout()
        self.hbox5.addWidget(self.checkbox1)
        self.hbox5.addWidget(self.label4)
        self.hbox5.addWidget(self.pushButton3)

        self.vbox1 = QVBoxLayout()
        self.vbox1.addLayout(self.hbox5)

        self.setLayout(self.vbox1)

        self.autoResolve = hoverDialog(self)

    def eventFilter(self, obj, event):
        if obj == self.label4 and event.type() == QtCore.QEvent.Enter and self.autoResolve.isHidden():
            self.onHovered()
        return super().eventFilter(obj, event)

    def onHovered(self):
        pos = QtGui.QCursor.pos()
        self.autoResolve.move(pos)
        self.autoResolve.show()

    def buttonPressed(self):
        if self.checkbox.isChecked():
            print('do something..')

if __name__ == '__main__':
    app = QApplication(sys.argv)
    form = Table()
    form.show()
    app.exec_()

【问题讨论】:

【参考方案1】:

查看来源,我认为问题的根源在于每当显示新的弹出窗口小部件时 Qt 的行为。

我不能保证 100%,但无论如何最简单的解决方案是仅在未显示组合弹出窗口时隐藏小部件:

def leaveEvent(self, event):
    if not self.combobox.view().isVisible():
        self.hide()

请注意,您的方法并不完美:由于对话框可能会显示当前鼠标位置之外的几何图形,因此在鼠标实际进入之前,它无法隐藏自身。您可能还应该过滤 FocusOut 和 WindowDeactivate 事件。

【讨论】:

谢谢,效果很好!根据您的建议,我尝试使用 QLabel 和 QDialog 的事件过滤器,但似乎无法获得“全部捕获”逻辑。最后,我决定修改下面的内容,使光标在显示时始终位于 QDialog 内部 (self.autoResolve.move(pos.x()-5, pos.y()-5))。 处理与当前***窗口不“同级”的小部件中发生的事件并不总是那么容易:总是需要一些良好的经验,您还必须考虑可能发生的事件取决于操作系统。您的解决方案确实是最简单和合乎逻辑的解决方案;更全面的一种可能是将事件过滤器直接安装到 QApplication 过滤器焦点、鼠标、窗口激活事件,并最终隐藏不属于它或其子级的“弹出窗口”。

以上是关于QComboBox 点击触发主 QDialog 上的 leaveEvent的主要内容,如果未能解决你的问题,请参考以下文章

qt 不点击按钮触发按钮clicked事件

QDialog 在添加新小部件时将小部件涂成黑色

如何从另一个类 PyQT 向 QComboBox 添加项目?

根据多个 QComboBox 的文本启用或禁用 QDialogBu​​ttonBox

在 Mac 上单击主窗口时,QDialog as Popup 不会隐藏

隐藏 qdialog 并显示主窗口