Rt Rtt
Rt Rtt

Reputation: 617

PyQt5: QPainter overlay QWidget

To this question I am referring to the answer from @Kuba Ober Draw Rectangular overlay on QWidget at click

My problem: I dont know how to "translate" the C++ (or C?) into Python. :-(

Thus I ask this "duplicated" question again, and wish anyone would help to rewrite the code to achieve the overlay effect in PyQt5.

As an example, I prepare here some code:

# -*- coding: utf-8 -*-

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

class MyApp(QWidget):
    def __init__(self):
        super(MyApp, self).__init__()
        self.initUI()

    def initUI(self):
        self.text = "hello world"
        self.setGeometry(100, 100, 400, 300)
        self.setWindowTitle('Draw Demo')

        self.btn = QPushButton("Butten should be overlayed", self)
        self.btn.setFixedSize(200, 200)
        self.btn.move(40, 40)

        self.show()

    def paintEvent(self, event):
        qp = QPainter()
        qp.begin(self)
        qp.setPen(QColor(Qt.red))
        qp.setFont(QFont('Arial', 20))

        qp.drawText(10, 50, "hello Python")
        qp.setPen(QColor(Qt.blue))
        qp.drawLine(10, 100, 100, 100)
        qp.drawRect(10, 150, 150, 100)

        qp.setPen(QColor(Qt.red))
        qp.drawEllipse(100, 50, 100, 50)
#        qp.drawPixmap(220, 10, QPixmap("python.jpg"))
        qp.fillRect(200, 175, 150, 100, QBrush(Qt.SolidPattern))
        qp.end()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = MyApp()
    window.show()
    sys.exit(app.exec_())

Target is: Let the Button shown in the background (overlayed by QPainter), but it is transparent to mouse event. Thus I could click the button, even though it is covered by QPainter.

Any help will be highly appreciated!

Upvotes: 0

Views: 2146

Answers (1)

eyllanesc
eyllanesc

Reputation: 244282

The translation from C ++ to Python is simple if we know the equivalences and differences between both languages as I show below:

overLay.py

import sys

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


class OverLay(QWidget):
    def __init__(self, *args, **kwargs):
        QWidget.__init__(self, *args, **kwargs)
        self.setAttribute(Qt.WA_NoSystemBackground)
        self.setAttribute(Qt.WA_TransparentForMouseEvents)

    def paintEvent(self, event):
        painter = QPainter(self)
        painter.fillRect(self.rect(), QColor(80, 80, 255, 128))

class Filter(QObject):
    def __init__(self, *args, **kwargs):
        QObject.__init__(self, *args, **kwargs)
        self.m_overlay = None
        self.m_overlayOn = None

    def eventFilter(self, obj, event):
        if not obj.isWidgetType():
            return False
        if event.type() == QEvent.MouseButtonPress:
            if not self.m_overlay:
                self.m_overlay = OverLay(obj.parentWidget())
            self.m_overlay.setGeometry(obj.geometry())
            self.m_overlayOn = obj
            self.m_overlay.show()
        elif event.type() == QEvent.Resize:
            if self.m_overlay and self.m_overlayOn == obj:
                self.m_overlay.setGeometry(obj.geometry())
        return False


if __name__ == '__main__':
    app = QApplication(sys.argv)
    filt = Filter()
    window = QWidget()
    lay = QHBoxLayout(window)
    for text in ( "Foo", "Bar", "Baz "):
        label = QLabel(text)
        lay.addWidget(label)
        label.installEventFilter(filt)
    window.setMinimumSize(300, 250)
    window.show()
    sys.exit(app.exec_())

Understanding what you want to do in your widget you must use the following code:

main.py

# -*- coding: utf-8 -*-

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

from overlay import Filter


class MyApp(QWidget):
    def __init__(self):
        super(MyApp, self).__init__()
        self.initUI()

    def initUI(self):
        self.text = "hello world"
        self.setGeometry(100, 100, 400, 300)
        self.setWindowTitle('Draw Demo')

        self.btn = QPushButton("Butten should be overlayed", self)
        self.btn.setFixedSize(200, 200)
        self.btn.move(40, 40)
        filt = Filter(self)
        self.btn.installEventFilter(filt)

        self.show()

    [...]

if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = MyApp()
    window.show()
    sys.exit(app.exec_())

Upvotes: 1

Related Questions