python - 如何获取 QPaintEvent 覆盖下的小部件以注册鼠标事件

标签 python python-2.7 pyside2

我正在使用带有 QPaintEvent 的覆盖层来绘制其他小部件。我仍然需要下面的小部件来注册鼠标事件。当我使用 WA_TransparentForMouseEvents 标志调用 raise() 时,我再次获得了对小部件的控制,但是当然,丢失了paintevent,因为它不再注册任何鼠标事件。我在这里有什么选择?

class Overlay(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super(Overlay, self).__init__(parent)

        self.hotBox = parent
        self.resize(self.hotBox.width, self.hotBox.height)


    def paintEvent(self, event):
        #args: [QEvent]
        if any ([self.hotBox.name=="main", self.hotBox.name=="viewport"]):
            self.raise_()
            self.setWindowFlags(QtCore.Qt.WA_TransparentForMouseEvents)

            #Initialize painter
            painter = QtGui.QPainter(self)
            pen = QtGui.QPen(QtGui.QColor(115, 115, 115), 3, QtCore.Qt.SolidLine, QtCore.Qt.RoundCap, QtCore.Qt.RoundJoin)
            painter.setPen(pen)
            painter.setRenderHint(QtGui.QPainter.Antialiasing, True)
            painter.setBrush(QtGui.QColor(115, 115, 115))
            painter.drawEllipse(self.hotBox.point, 5, 5)

            #perform paint
            if self.hotBox.mousePosition:
                mouseX = self.hotBox.mousePosition.x()
                mouseY = self.hotBox.mousePosition.y()
                line = QtCore.QLine(mouseX, mouseY, self.hotBox.point.x(), self.hotBox.point.y())
                painter.drawLine(line)
                painter.drawEllipse(mouseX-5, mouseY-5, 10, 10)

最佳答案

如果您想使用事件 mouseXXXEvent 创建覆盖,则必须使用 eventFilter,对于此解决方案,我基于 this answer@KubaOber添加更多功能:

import sys
from PySide2 import QtCore, QtGui, QtWidgets


class Overlay(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super(Overlay, self).__init__(parent)
        self.setAttribute(QtCore.Qt.WA_NoSystemBackground)
        self.setAttribute(QtCore.Qt.WA_TransparentForMouseEvents)

        self.start_line, self.end_line = QtCore.QPoint(), QtCore.QPoint()

    def paintEvent(self, event):
        painter = QtGui.QPainter(self)
        painter.fillRect(self.rect(), QtGui.QColor(80, 80, 255, 128))
        if not self.start_line.isNull() and not self.end_line.isNull():
            painter.drawLine(self.start_line, self.end_line)

    def mousePressEvent(self, event):
        self.start_line = event.pos()
        self.end_line = event.pos()
        self.update()

    def mouseMoveEvent(self, event):
        self.end_line = event.pos()
        self.update()

    def mouseReleaseEvent(self, event):
        self.start_line = QtCore.QPoint()
        self.end_line = QtCore.QPoint()

class OverlayFactoryFilter(QtCore.QObject):
    def __init__(self, parent=None):
        super(OverlayFactoryFilter, self).__init__(parent)
        self.m_overlay = None

    def setWidget(self, w):
        w.installEventFilter(self)
        if self.m_overlay is None:
            self.m_overlay = Overlay()
        self.m_overlay.setParent(w)

    def eventFilter(self, obj, event):
        if not obj.isWidgetType():
            return False

        if event.type() == QtCore.QEvent.MouseButtonPress:
            self.m_overlay.mousePressEvent(event)
        elif event.type() == QtCore.QEvent.MouseButtonRelease:
            self.m_overlay.mouseReleaseEvent(event)
        elif event.type() == QtCore.QEvent.MouseMove:
            self.m_overlay.mouseMoveEvent(event)
        elif event.type() == QtCore.QEvent.MouseButtonDblClick:
            self.m_overlay.mouseDoubleClickEvent(event)

        elif event.type() == QtCore.QEvent.Resize:
            if self.m_overlay and self.m_overlay.parentWidget() == obj:
                self.m_overlay.resize(obj.size())
        elif event.type() == QtCore.QEvent.Show:
            self.m_overlay.raise_()
        return super(OverlayFactoryFilter, self).eventFilter(obj, event)


if __name__ == '__main__':
    import sys
    app = QtWidgets.QApplication(sys.argv)
    factory = OverlayFactoryFilter()
    w = QtWidgets.QWidget()
    factory.setWidget(w)
    button = QtWidgets.QPushButton("Press me", w)
    w.show()
    sys.exit(app.exec_())

关于python - 如何获取 QPaintEvent 覆盖下的小部件以注册鼠标事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52485404/

相关文章:

python - 编写此 elementTree 搜索操作的更好方法?

python - 在 PyTorch 的特定索引上将一个张量合并到另一个张量中

Python,括号对打印语句中 bool 值的影响

python - 无法使用 pyside2 和 QtDesigner 在我的主窗口中导入我的小部件

python - 弧形中的不同颜色

python - 如何使用线程正确结束程序?

python - lxml解析器吃掉所有内存

python - 安装 CPLEX 12.6 for Python 时出错

python-2.7 - python, paramiko, ssh 异常 ssh session 未激活

python - 将 Qt 嵌入 native 窗口 (Windows)