Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Integrating QPainter in PyQt GUI

I'm trying to use QPainter-made object along with native widgets of PyQt in one layout and having a difficulty doing so.

I've tried using addWidget() to add it to the layout but no luck.

class window(QWidget):
    def __init__(self):
        super().__init__()
        self.resize(600, 500)
        self.setWindowTitle('GUI 2.0')

        #LCD
        self.lcd = QLCDNumber()
        self.lcd.setFixedHeight(100)

        #Slider
        self.slider = QSlider(Qt.Horizontal)
        self.slider.setMaximum(40)
        self.slider.setMinimum(0)
        self.slider.valueChanged.connect(self.progress)

        #Push button
        pb = QPushButton('Button', self)
        pb.clicked.connect(self.button)

        #Progress Bar
        self.pbar = QProgressBar(self)
        self.pbar.setGeometry(30, 40, 200, 25)
        self.pbar.setTextVisible(False)

        #Qpainter
        painter = QPainter()
        painter.setPen(QPen(Qt.black, 5, Qt.SolidLine))
        painter.setBrush(QBrush(Qt.green, Qt.DiagCrossPattern))
        painter.drawRect(100, 15, 400,200)

        #Grid Layout 
        layout = QGridLayout()
        layout.addWidget(self.lcd, 1, 1)
        layout.addWidget(self.slider, 2, 1)
        layout.addWidget(pb, 2, 2)
        layout.addWidget(self.pbar, 0, 1)
        layout.addWidget(painter) # doesn't work!

        self.setLayout(layout)

My aim is for something like this where the slider will eventually change the water level in the tank and the button will reset the slider value and therefore empty the tank:

Water Tank

Water Tank

Whereas I have something like this:

Self-Made

How can I add the painter object to the layout?

like image 339
AmmarYasir Avatar asked Dec 01 '25 07:12

AmmarYasir


1 Answers

QPainter is not a widget but only paints on a device (QWidget, QImage, QPixmap, etc.), so in your case you must create a custom widget where in the paintEvent method the tank is painted

from PyQt5 import QtCore, QtGui, QtWidgets


class TankWidget(QtWidgets.QWidget):
    progressChanged = QtCore.pyqtSignal(float)

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

        self._progress = 0.0

    @QtCore.pyqtProperty(float, notify=progressChanged)
    def progress(self):
        return self._progress

    @progress.setter
    def progress(self, p):
        if 0 <= p <= 1.0:
            self._progress = p
            self.progressChanged.emit(p)
            self.update()

    def paintEvent(self, event):
        painter = QtGui.QPainter(self)
        height = self.progress * self.height()

        r = QtCore.QRect(0, self.height() - height, self.width(), height)
        painter.fillRect(r, QtGui.QBrush(QtCore.Qt.blue))
        pen = QtGui.QPen(QtGui.QColor("red"), 10)
        painter.setPen(pen)
        painter.drawRect(self.rect())

    def sizeHint(self):
        return QtCore.QSize(100, 100)


class Widget(QtWidgets.QWidget):
    def __init__(self):
        super().__init__()
        self.resize(600, 500)
        self.setWindowTitle("GUI 2.0")

        self.tank = TankWidget()
        self.progressbar = QtWidgets.QProgressBar()
        self.lcd = QtWidgets.QLCDNumber()
        self.lcd.setFixedHeight(100)
        self.slider = QtWidgets.QSlider(QtCore.Qt.Horizontal, maximum=101)
        self.button = QtWidgets.QPushButton("Button")

        self.slider.valueChanged.connect(self.on_value_changed)

        lay = QtWidgets.QGridLayout(self)
        lay.addWidget(self.tank, 0, 0, 2, 1)
        lay.addWidget(QtWidgets.QLabel("Tank", alignment=QtCore.Qt.AlignCenter), 2, 0)
        lay.addWidget(self.progressbar, 0, 1)
        lay.addWidget(self.lcd, 1, 1)
        lay.addWidget(self.slider, 2, 1)
        lay.addWidget(
            QtWidgets.QLabel(
                pixmap=QtGui.QPixmap("warning.png"), alignment=QtCore.Qt.AlignCenter
            ),
            0,
            2,
            2,
            1,
        )
        lay.addWidget(self.button, 2, 2)

        self.setFixedHeight(self.sizeHint().height())

        self.slider.setValue(40)

    @QtCore.pyqtSlot()
    def on_value_changed(self):
        progress = self.slider.value() * 1.0 / self.slider.maximum()
        self.tank.progress = progress
        self.progressbar.setValue(self.slider.value())
        self.lcd.display(self.slider.value())


if __name__ == "__main__":
    import sys

    app = QtWidgets.QApplication(sys.argv)
    w = Widget()
    w.show()
    sys.exit(app.exec_())

enter image description here

like image 143
eyllanesc Avatar answered Dec 02 '25 21:12

eyllanesc



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!