Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

QLabel paintEvent only Pixmap area



  • Hello,
    I have rounded image file, using setPixmap function to set image to QLabel.
    Everythings work fine but I need to custom paintEvent.

    As you can see in picture;
    There is a gray area outside the picture, i don't want this. I want this gray area only in picture.
    BIR.png

    Example:
    IKI.png

    My PaintEvent:

        def paintEvent(self, event):
            QLabel.paintEvent(self, event)
            painter = QPainter(self)
            painter.setRenderHint(painter.Antialiasing)
            painter.setBrush(QBrush(Qt.black, Qt.SolidPattern))
            painter.setOpacity(0.15)
            path = QPainterPath()
            path.setFillRule(Qt.WindingFill)
            painter.drawRect(QRect(self.width()*self.Percentage/100,0, self.width(),self.height()))
            painter.setOpacity(1)
            path.closeSubpath()
            painter.setClipPath(path)
            painter.drawPath(path.simplified())
    
    

    Thanks :)


  • Lifetime Qt Champion

    Hi,

    Does that image have a transparent background ?



  • @SGaist Yes image have a transparent background.
    My goal is; draw gray to image when mouse is not clicking. While mouse is clicking this gray should be gone step by step.
    I can do this with mousePressEvent, mouseReleaseEvent.
    But on this paintEvent I couldn't hide this gray area out of image.


  • Lifetime Qt Champion

    There's one thing not clear.

    Do you have your image shown properly by default ? So without any border for the transparent background ?



  • Setting tranparent to your label background will do it. No extra paint is needed.



  • @SGaist Yes It shows fine default (without paintEvent).
    But I am trying to do holding button (needs to hold for x second to activate);
    Video: streamable

    Everything works fine but I need to remove this gray area outside of image.
    I can't use constant border radius because some images may be have not border radius.
    So I need to draw this gray color to only showed area ( not all rectangle )

    All my code:

    # -*- coding: utf-8 -*-
    from PySide6 import QtCore, QtGui, QtWidgets
    from PySide6.QtWidgets import QWidget, QLabel, QApplication, QPushButton
    from PySide6.QtCore import QSize, Qt, Signal,QRect, QPoint, QTimer, QPropertyAnimation, QRectF
    from PySide6.QtGui import QColor, QFont, QPixmap, QPainter,QPen, QBrush, QPainterPath, QLinearGradient, QIcon
    import time
    
    class HoldButton(QLabel):
        Text=""
        MaxHoldSecond=0.5
        PressedTimeMS = 0
        Percentage = 0 # [0 - 100]
        def __init__(self, Text, PixmapPath=None, MaxHoldSecond=0.5, parent=None):
            super(HoldButton, self).__init__(parent)
            self.Text, self.MaxHoldSecond, self.parent = Text, MaxHoldSecond, parent
            self.setText(Text)
            self.setFont(QFont('Exo 2', 14))
            self.setAlignment(Qt.AlignCenter)
            if PixmapPath != None:
                self.setPixmap(QPixmap(PixmapPath))
            self.timer_button = QTimer(self)
    
            self.timer_button.timeout.connect(self.TmrEvent)
        def TmrEvent(self):
            self.PressedTimeMS += 0.001
            self.Percentage += self.PressedTimeMS / max(self.MaxHoldSecond, 0.1)*10
            self.Percentage = min(100, max(0, self.Percentage))
            print("still left clicking...")
            self.repaint()
    
        def paintEvent(self, event):
            QLabel.paintEvent(self, event)
            painter = QPainter(self)
            painter.setRenderHint(painter.Antialiasing)
            painter.setBrush(QBrush(Qt.black, Qt.SolidPattern))
            painter.setOpacity(0.15)
            path = QPainterPath()
            path.setFillRule(Qt.WindingFill)
            painter.drawRect(QRect(self.width()*self.Percentage/100,0, self.width(),self.height()))
            painter.setOpacity(1)
            path.closeSubpath()
            painter.setClipPath(path)
            painter.drawPath(path.simplified())
    
        _Pressing = False
        def mousePressEvent(self, event):
            if event.button()!=Qt.LeftButton:return
            self._Pressing=True
            print("left click start")
            self.timer_button.start(10)
    
            QLabel.mousePressEvent(self, event)
    
        def mouseReleaseEvent(self, event):
            if event.button() != Qt.LeftButton: return
            self._Pressing=False
            print("left click end")
            print("Button held for: %f"% self.PressedTimeMS)
            self.timer_button.stop()
            self.PressedTimeMS=0
            def tmrZeroPercentageSlowly(tmr):
                if self.Percentage > 0:
                    self.Percentage -= 1
                    self.repaint()
                else:
                    tmr.stop()
                    tmr.deleteLater()
                if self._Pressing:
                    tmr.stop()
                    tmr.deleteLater()
                self.Percentage = min(100, max(0, self.Percentage))
            if self.Percentage == 100:
                def ToZero():
                    while self.Percentage > 0:
                        self.Percentage -= 2
                        self.repaint()
                        time.sleep(0.001)
    
                QTimer.singleShot(1, ToZero)
                self.repaint()
                self.Successful()
                return
    
            tmrSlow = QTimer(self)
            tmrSlow.timeout.connect(lambda: tmrZeroPercentageSlowly(tmrSlow))
            tmrSlow.start(10)
            QLabel.mouseReleaseEvent(self, event)
    
        def Successful(self):
            print("Successful")
    


  • Any idea?