Design of windows 10 battery charging inspired progress bar using pyside

589 Views Asked by At

Need help to develop a progress bar in pyside like what we see in windows 10. while charging it has to show the progress bar along with the plug symbol.

enter image description here

After full charge the progress bar should be like below

enter image description here

Already I developed the code for horizontal progress bar. I need to emboss progress bar image attached above over the existing progress bar. Here is my code

def initUI(self): 
        self.pbar = QtGui.QProgressBar(self)
        self.pbar.setGeometry(30, 40, 300, 25)
        self.pbar.setAlignment(QtCore.Qt.AlignCenter) 
        self.pbar.setMinimum(0)
        self.pbar.setValue(y)
        self.pbar.setValue(40)

        self.pbar.setRange(0,100)
        self.pbar.setStyleSheet("QProgressBar::chunk"
                         "{"
                         "background-color: Green;"
                         "margin: 4px;"
                         "}")
           
        self.setGeometry(300, 300, 480, 170)
        self.setWindowTitle('ProgressBar')

I am trying to send serial data from Arduino Uno so that progress bar has to progress according to the serial data. Its starts at 30% and ends at 100% and again rolls back to 30%. But When I compile the code I got the progress bar image with 30% progress value and after that it is not progressing. I am also getting some errors when i compile the code. Here is my full code

import serial
import time
import sys
from PySide.QtGui import *
from PySide import QtGui, QtCore
from PySide.QtCore import Signal

from time import sleep
list=['COM1','COM2','COM3','COM4','COM5','COM6','COM7','COM8','COM9','COM10','COM11','COM12','COM13','COM14','COM15','COM16','COM17','COM18',]
COM1='COM1'
COM2='COM2'
COM3='COM3'
COM4='COM4'
COM5='COM5'
COM6='COM6'
COM7='COM7'
COM8='COM8'
COM9='COM9'
COM10='COM10'
COM11='COM11'
COM12='COM12'
COM13='COM13'
COM14='COM14'
COM15='COM15'
COM16='COM16'
COM17='COM17'
COM18='COM18'
COM19='COM19'
time.sleep(1)
ser = serial.Serial()
i=1
while True:
    time.sleep(.2)
    print(i)
    ser.port = list[i]
    try:

        ser.open()
        if ser.isOpen()==True:
            print('connected')
            #print('arduino is on COMPORT'.join(i))
            break
        break

    except:
        print('waiting')
        i=i+1
        if i==18:
            print('Kindly remove usb cable and try again')
            break

ser.baudrate = 9600
x = ser.readline()
y = int(x)

class Battery(QProgressBar):

    def __init__(self, *args, **kwargs):
        super(Battery,self).__init__(*args, **kwargs)
        self.setTextVisible(False)
        self.charging = False
        self.setStyleSheet('''
        QProgressBar {
            border: 4px solid white;
            background-color: #0070db;
            margin-top: 12px;
        }
        QProgressBar:horizontal {
            height: 60px;
            width: 120px;
            margin-right: 12px;
        }
        QProgressBar:vertical {
            height: 120px;
            width: 60px;
            margin-left: 12px;
        }
        QProgressBar::chunk {
            background-color: white;
            margin: 4px;
        }''')

    def setCharging(self, state):
        self.charging = state
        self.repaint()

    def paintEvent(self, event):
        super(Battery,self).paintEvent(event)
        qp = QPainter(self)
        qp.setPen(QtCore.Qt.NoPen); qp.setBrush(QtCore.Qt.white)
        w, h = self.width(), self.height()
        if self.orientation() == QtCore.Qt.Horizontal:
            qp.drawRect(w, 12 + h / 4, -12, h / 2 - 12)
            dx, dy = 0, 12
        else:
            qp.drawRect(12 + w / 4, 0, w / 2 - 12, 12)
            dx, dy = 12, 0

        qp.setPen(self.palette().text().color())
        qp.drawText(self.rect().adjusted(dx, dy, 0, 0), QtCore.Qt.AlignCenter, self.text())
        qp.setPen(QtCore.Qt.NoPen)
        
        if self.charging:
            qp.setBrush(self.parent().palette().window())
            path = QPainterPath()
            if self.orientation() == QtCore.Qt.Horizontal:
                qp.drawRect(0, 0, 12, h)
                path.moveTo(12, h)
                path.lineTo(12, 12 + h / 3)
                path.quadTo(22, 12 + h / 3, 22, 24)
                path.lineTo(22, 14)
                path.lineTo(2, 14)
                path.lineTo(2, 24)
                path.quadTo(2, 12 + h / 3, 12, 12 + h / 3)
                path.moveTo(7, 12); path.lineTo(7, 0)
                path.moveTo(17, 12); path.lineTo(17, 0)
            else:
                qp.drawRect(0, h, w, -12)
                path.moveTo(w, h - 12)
                path.lineTo(12 + w / 3, h - 12)
                path.quadTo(12 + w / 3, h - 22, 24, h - 22)
                path.lineTo(14, h - 22)
                path.lineTo(14, h - 2)
                path.lineTo(24, h - 2)
                path.quadTo(12 + w / 3, h - 2, 12 + w / 3, h - 12)
                path.moveTo(12, h - 7); path.lineTo(0, h - 7)
                path.moveTo(12, h - 17); path.lineTo(0, h - 17)
            
            pen = QPen(qp.brush(), 12, QtCore.Qt.SolidLine, QtCore.Qt.SquareCap, QtCore.Qt.MiterJoin)
            qp.strokePath(path, pen)
            pen.setWidth(4); pen.setColor(QtCore.Qt.white); qp.setPen(pen)
            qp.setBrush(self.palette().window())
            qp.drawPath(path)

class Template(QWidget):

    def __init__(self):
        super(Template, self).__init__()
        grid = QGridLayout(self)
        grid.setSpacing(50)
        pbar = Battery(value=y)
        pbar.setCharging(True)
        grid.addWidget(Battery(value=y), 0, 0)
        grid.addWidget(pbar, 0, 1)
        
        pbar = Battery(value=y, orientation=QtCore.Qt.Vertical)
        pbar.setCharging(True)
        grid.addWidget(Battery(value=y, orientation=QtCore.Qt.Vertical), 1, 0, QtCore.Qt.AlignCenter)
        grid.addWidget(pbar, 1, 1, QtCore.Qt.AlignCenter)
        self.setStyleSheet('''
        Template {
            background-color: #0070db;
        }''')
        self.myLongTask = TaskThread()
        # connect signal before thresd is started
        self.myLongTask.notifyProgress.connect(self.on_progress)
        # start thread
        self.on_start()
        

    
    def on_start(self):
        self.myLongTask.start()

    def on_progress(self, y):
        self.pbar.setValue(y)


class TaskThread(QtCore.QThread):
   #notifyProgress = QtCore.pyqtSignal(int)
   notifyProgress = Signal(int)

   def run(self):
        while True:
            x = ser.readline()
            y = int(x)
            #for y in range(100):
            self.notifyProgress.emit(y)
       #    sleep(0.1)

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

when i compile the code i got the following error

File "C:\Python27\winbat.py", line 166, in on_progress
    self.pbar.setValue(y)
AttributeError: 'Template' object has no attribute 'pbar'

And This is my arduino uno code

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
}

void loop() {
  // put your main code here, to run repeatedly:
  //Serial.println("hello");
  for (int i = 30; i <= 100; i++) {
  Serial.println(i);
  delay(1000);
}
}

This is the output iam getting enter image description here

1

There are 1 best solutions below

3
On

You could subclass QProgressBar and draw it with QPainter.

class Battery(QProgressBar):

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.setTextVisible(False)
        self.charging = False
        self.setStyleSheet('''
        QProgressBar {
            border: 4px solid white;
            background-color: #0070db;
            margin-top: 12px;
        }
        QProgressBar:horizontal {
            height: 60px;
            width: 120px;
            margin-right: 12px;
        }
        QProgressBar:vertical {
            height: 120px;
            width: 60px;
            margin-left: 12px;
        }
        QProgressBar::chunk {
            background-color: white;
            margin: 4px;
        }''')

    def setCharging(self, state):
        self.charging = state
        self.repaint()

    def paintEvent(self, event):
        super().paintEvent(event)
        qp = QPainter(self)
        qp.setPen(Qt.NoPen); qp.setBrush(Qt.white)
        w, h = self.width(), self.height()
        if self.orientation() == Qt.Horizontal:
            qp.drawRect(w, 12 + h / 4, -12, h / 2 - 12)
            dx, dy = 0, 12
        else:
            qp.drawRect(12 + w / 4, 0, w / 2 - 12, 12)
            dx, dy = 12, 0

        qp.setPen(self.palette().text().color())
        qp.drawText(self.rect().adjusted(dx, dy, 0, 0), Qt.AlignCenter, self.text())
        qp.setPen(Qt.NoPen)
        
        if self.charging:
            qp.setBrush(self.parent().palette().window())
            path = QPainterPath()
            if self.orientation() == Qt.Horizontal:
                qp.drawRect(0, 0, 12, h)
                path.moveTo(12, h)
                path.lineTo(12, 12 + h / 3)
                path.quadTo(22, 12 + h / 3, 22, 24)
                path.lineTo(22, 14)
                path.lineTo(2, 14)
                path.lineTo(2, 24)
                path.quadTo(2, 12 + h / 3, 12, 12 + h / 3)
                path.moveTo(7, 12); path.lineTo(7, 0)
                path.moveTo(17, 12); path.lineTo(17, 0)
            else:
                qp.drawRect(0, h, w, -12)
                path.moveTo(w, h - 12)
                path.lineTo(12 + w / 3, h - 12)
                path.quadTo(12 + w / 3, h - 22, 24, h - 22)
                path.lineTo(14, h - 22)
                path.lineTo(14, h - 2)
                path.lineTo(24, h - 2)
                path.quadTo(12 + w / 3, h - 2, 12 + w / 3, h - 12)
                path.moveTo(12, h - 7); path.lineTo(0, h - 7)
                path.moveTo(12, h - 17); path.lineTo(0, h - 17)
            
            pen = QPen(qp.brush(), 12, Qt.SolidLine, Qt.SquareCap, Qt.MiterJoin)
            qp.strokePath(path, pen)
            pen.setWidth(4); pen.setColor(Qt.white); qp.setPen(pen)
            qp.setBrush(self.palette().window())
            qp.drawPath(path)

Call setCharging(True) to draw the plug.

class Template(QWidget):

    def __init__(self):
        super().__init__()
        grid = QGridLayout(self)
        grid.setSpacing(50)
        pbar = Battery(value=100)
        pbar.setCharging(True)
        grid.addWidget(Battery(value=100), 0, 0)
        grid.addWidget(pbar, 0, 1)
        
        pbar = Battery(value=100, orientation=Qt.Vertical)
        pbar.setCharging(True)
        grid.addWidget(Battery(value=100, orientation=Qt.Vertical), 1, 0, Qt.AlignCenter)
        grid.addWidget(pbar, 1, 1, Qt.AlignCenter)
        self.setStyleSheet('''
        Template {
            background-color: #0070db;
        }''')


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

enter image description here