Jayant
Jayant

Reputation: 15

How to put a widget on a background image in QMainWindow in Pyqt5?

I have a custom LED indicator widget(from github), which looks like this on QMainWindow:

enter image description here

I have an image which I can put in the backgroud of the QMainWindow like this:

enter image description here

Now my quesion is, How do I put the LED indicator widget OVER the background image(I want to put them in all the boxes)? The LED indicator widget is not showing up at all when I put a background image in the program.

This is the code:

import sys
from LedIndicatorWidget import *
from PyQt5 import QtCore, QtWidgets
from PyQt5.QtWidgets import QMainWindow, QLabel, QCheckBox, QWidget
from PyQt5.QtCore import QSize    

class ExampleWindow(QMainWindow):
    def __init__(self):
        QMainWindow.__init__(self)
        self.setMinimumSize(QSize(300, 300))    
        self.setWindowTitle("Checkbox")

        oImage = QImage("map.png")
        sImage = oImage.scaled(QSize(800,277))                   
        palette = QPalette()
        palette.setBrush(QPalette.Window, QBrush(sImage))                        
        self.setPalette(palette)

        self.show()

    
    

        self.led = LedIndicator(self)
        self.led.setDisabled(True)  
    
    
        self.led.move(10,20)
        self.led.resize(100,100)

        self.led1 = LedIndicator(self)
        self.led1.setDisabled(True)  
    
    
        self.led1.move(150,20)
        self.led1.resize(100,100)

        self.led2 = LedIndicator(self)
        self.led2.setDisabled(True)  
    
    
        self.led2.move(300,20)
        self.led2.resize(100,100)
    
    
    
        self.timer = QtCore.QTimer()
    
    
        self.timer.timeout.connect(self.onPressButton)
        self.timer.start()
    


    def onPressButton(self):
    
    
        self.led.setChecked(not self.led.isChecked())
        self.timer.stop()
     
if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    mainWin = ExampleWindow()
    mainWin.show()
    sys.exit( app.exec_() )

I've used Qpalette for the background image, if you have a better idea to add the image and make it work, feel free to do so, because I couldn't find one.

To use the LED indicator widget, make a file "LedIndicatorWidget.py" and copy this code:

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


class LedIndicator(QAbstractButton):
    scaledSize = 1000.0

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

        self.setMinimumSize(24, 24)
        self.setCheckable(True)

        # Green
        self.on_color_1 = QColor(0, 255, 0)
        self.on_color_2 = QColor(0, 192, 0)
        self.off_color_1 = QColor(0, 28, 0)
        self.off_color_2 = QColor(0, 128, 0)

    def resizeEvent(self, QResizeEvent):
        self.update()

    def paintEvent(self, QPaintEvent):
        realSize = min(self.width(), self.height())

        painter = QPainter(self)
        pen = QPen(Qt.black)
        pen.setWidth(1)

        painter.setRenderHint(QPainter.Antialiasing)
        painter.translate(self.width() / 2, self.height() / 2)
        painter.scale(realSize / self.scaledSize, realSize / self.scaledSize)

        gradient = QRadialGradient(QPointF(-500, -500), 1500, QPointF(-500, -500))
        gradient.setColorAt(0, QColor(224, 224, 224))
        gradient.setColorAt(1, QColor(28, 28, 28))
        painter.setPen(pen)
        painter.setBrush(QBrush(gradient))
        painter.drawEllipse(QPointF(0, 0), 500, 500)

        gradient = QRadialGradient(QPointF(500, 500), 1500, QPointF(500, 500))
        gradient.setColorAt(0, QColor(224, 224, 224))
        gradient.setColorAt(1, QColor(28, 28, 28))
        painter.setPen(pen)
        painter.setBrush(QBrush(gradient))
        painter.drawEllipse(QPointF(0, 0), 450, 450)

        painter.setPen(pen)
        if self.isChecked():
            gradient = QRadialGradient(QPointF(-500, -500), 1500, QPointF(-500, -500))
            gradient.setColorAt(0, self.on_color_1)
            gradient.setColorAt(1, self.on_color_2)
        else:
            gradient = QRadialGradient(QPointF(500, 500), 1500, QPointF(500, 500))
            gradient.setColorAt(0, self.off_color_1)
            gradient.setColorAt(1, self.off_color_2)

        painter.setBrush(gradient)
        painter.drawEllipse(QPointF(0, 0), 400, 400)

    @pyqtProperty(QColor)
    def onColor1(self):
        return self.on_color_1

    @onColor1.setter
    def onColor1(self, color):
        self.on_color_1 = color

    @pyqtProperty(QColor)
    def onColor2(self):
        return self.on_color_2

    @onColor2.setter
    def onColor2(self, color):
        self.on_color_2 = color

    @pyqtProperty(QColor)
    def offColor1(self):
        return self.off_color_1

    @offColor1.setter
    def offColor1(self, color):
        self.off_color_1 = color

    @pyqtProperty(QColor)
    def offColor2(self):
        return self.off_color_2

    @offColor2.setter
    def offColor2(self, color):
        self.off_color_2 = color

Upvotes: 0

Views: 715

Answers (1)

musicamante
musicamante

Reputation: 48489

The issue is not related to the background: the LED widgets are there, the problem is that widgets added to a parent that is already shown (and without using a layout manager) does not make them visible, and they must be explicitly shown by calling show() or setVisible(True).

You can see the difference if you remove the self.show() line after setting the palette (but leaving the mainWin.show() at the end): in that case, the leds become automatically visible.

The solution is to either show the child widgets explicitly, or call show()/setVisible(True) on the parent after adding them.

Upvotes: 1

Related Questions