QT4 Progressbar


In this article we will demonstrate how to use the progressbar widget.  The progressbar is different from the other widgets in that it updates in time.

Related course:
Create Simple GUI Applications with Python and Qt

QT4 Progressbar Example
Let’s start with the code:

#! /usr/bin/env python
# -*- coding: utf-8 -*-
#
import sys
from PyQt4.QtGui import *
from PyQt4.QtCore import *
from PyQt4.QtCore import pyqtSlot,SIGNAL,SLOT
 
class QProgBar(QProgressBar):
 
    value = 0
 
    @pyqtSlot()
    def increaseValue(progressBar):
        progressBar.setValue(progressBar.value)
        progressBar.value = progressBar.value+1
 
# Create an PyQT4 application object.
a = QApplication(sys.argv)       
 
# The QWidget widget is the base class of all user interface objects in PyQt4.
w = QWidget()
 
# Set window size. 
w.resize(320, 240)
 
# Set window title  
w.setWindowTitle("PyQT4 Progressbar @ pythonspot.com ") 
 
# Create progressBar. 
bar = QProgBar(w)
bar.resize(320,50)    
bar.setValue(0)
bar.move(0,20)
 
# create timer for progressBar
timer = QTimer()
bar.connect(timer,SIGNAL("timeout()"),bar,SLOT("increaseValue()"))
timer.start(400) 
 
# Show window
w.show() 
 
sys.exit(a.exec_())

The instance bar (of class QProgBar) is used to hold the value of the progressbar.  We call the function setValue() to update its value.  The parameter w is given to attach it to the main window. We then move it to position (0,20) on the screen and give it a width and height.

To update the progressbar in time we need a QTimer().  We connect the widget with the timer, which calls the function increaseValue().  We set the timer to repeat the function call every 400 milliseconds.  You also see the words SLOT and SIGNAL.  If a user does an action such as clicking on a button, typing text in a box – the widget sends out a signal.  This signal does nothing, but it can be used to connect with a slot, that acts as a receiver and acts on it.

Result:

PyQT Progressbar

PyQT Progressbar

Download PyQT Code (Bulk Collection)

QT4 Pixmaps (Images)
Creating a web-browser with Python and PyQT
This entry was posted in QT4 and tagged , , , . Bookmark the permalink.

7 Responses to QT4 Progressbar

  1. Jahir Garcia says:

    hello, frank nice tutorials, Im really a beginner in python, but I use python on windows with arduino, I see on internet son gauge dial similar to this: https://developers.google.com/chart/interactive/docs/gallery/gauge, I see this example for do one dial with pyqt: http://stackoverflow.com/questions/12011147/how-to-create-a-3-color-gradient-dial-indicator-the-one-that-shows-green-yellow, Can you finished this example with numbers, and put published here. A question where are You from??

    • Frank says:

      Hi Jahir, I’m from the netherlands. This is how to create a gauge dial with set and get value:

      import sys
      from PyQt4 import QtGui, QtCore, Qt
      import math
       
      class QtGauge(QtGui.QWidget):
       
          value = 1
       
          def __init__(self):
              super(QtGauge, self).__init__()
              self.initUI()
       
          def setValue(self,value):
              self.value = value
       
          def getValue(self):
              return self.value
       
          def initUI(self):      
       
              hbox = QtGui.QHBoxLayout(self)
              lbl = QtGui.QLabel(self)
       
              hbox.addWidget(lbl)
              self.setLayout(hbox)
              self.setGeometry(0, 0,600,600)
       
              self.move(300, 200)
              self.setWindowTitle('Dial Guage')
              self.show()  
       
          def paintEvent(self, e):
              painter = QtGui.QPainter()
              painter.begin(self)
              dial = QtGui.QPixmap("bg.png")
              #painter.drawPixmap(50, 50, 600, 600, dial)
       
              painter.setRenderHint(painter.Antialiasing)
              rect = e.rect()
       
              gauge_rect = QtCore.QRect(rect)
              size = gauge_rect.size()
              pos = gauge_rect.center()
              gauge_rect.moveCenter( QtCore.QPoint(pos.x()-size.width(), pos.y()-size.height()) )
              gauge_rect.setSize(size*.9)
              gauge_rect.moveCenter(pos)
       
              refill_rect = QtCore.QRect(gauge_rect)
              size = refill_rect.size()
              pos = refill_rect.center()
              refill_rect.moveCenter( QtCore.QPoint(pos.x()-size.width(), pos.y()-size.height()) )
              # smaller than .9 == thicker gauge
              refill_rect.setSize(size*.9)
              refill_rect.moveCenter(pos)
       
              painter.setPen(QtCore.Qt.NoPen)
       
              painter.drawPixmap(rect, dial)
       
              painter.save()
              grad = QtGui.QConicalGradient(QtCore.QPointF(gauge_rect.center()), 270.0)
              grad.setColorAt(.75, QtCore.Qt.green)
              grad.setColorAt(.5, QtCore.Qt.yellow)
              grad.setColorAt(.1, QtCore.Qt.red)
              painter.setBrush(grad)
              #painter.drawPie(gauge_rect, 225.0*16, self._value*16)
              painter.drawPie(gauge_rect, 225.0*16, -270*self.value*16)
              painter.restore()
       
              painter.setBrush(QtGui.QBrush(dial.scaled(rect.size())))
              painter.drawEllipse(refill_rect)
       
              super(QtGauge,self).paintEvent(e)   
              painter.end()
       
       
      def main():
          app = QtGui.QApplication(sys.argv)
          ex = QtGauge()
          ex.setValue(0.6)
          print ex.getValue()
          sys.exit(app.exec_())
       
       
      if __name__ == '__main__':
          main()

      The background:
      https://pythonspot.com/wp-content/uploads/2015/07/bg.png

      It will tell the value of the gauge and you can set it on the scale of 0 to 1. Is this what you had in mind?

      • Jahir Garcia says:

        OK, Fantastic, But How I put the label values for scale on graphic. (0, 0.1, 0.2, 0.3 .. ….1), I see a beautiful gauges indicators in PYQT
        qt-apps.org/content/show.php/AnalogWidgets?content=87780
        But the code was writed for QT on C++, Is possible pass the code for use in PYQT windows??

        • Frank says:

          Hi, it’s possible to put these programatically but it looks much better if you simply modify the pixmap. As far as I know these C++ widgets are not ported. I saw this version uses a textfont pixmap that is put on top of the gauge. This is one possibility but I don’t know the advantage as to simply changing the background pixmap.

          If you want to put a label on a pixmap programatically, you can do something like this:

          import sys
          from PyQt4 import QtGui, QtCore, Qt
          import math
           
          from PyQt4.QtCore import *
          from PyQt4.QtGui import *
           
          class QtGauge(QtGui.QWidget):
           
              value = 1
           
              def __init__(self):
                  super(QtGauge, self).__init__()
                  self.initUI()
           
              def setValue(self,value):
                  self.value = value
           
              def getValue(self):
                  return self.value
           
              def initUI(self):      
           
                  hbox = QtGui.QVBoxLayout(self)
                  palette = QtGui.QPalette()
           
                  # create a label
                  lbl = QtGui.QLabel(self)
                  palette.setColor(QtGui.QPalette.Foreground,QtCore.Qt.red)
                  lbl.setPalette(palette)
                  lbl.resize(400, 200)
                  lbl.setText("Text on label")
                  lbl.setFont(QtGui.QFont('Decorative', 40))
                  lbl.move(0,0)
           
                  hbox.addWidget(lbl)
           
                  self.setLayout(hbox)
                  self.setGeometry(0, 0,600,600)
           
                  self.move(300, 200)
                  self.setWindowTitle('Dial Guage')
                  self.show()  
           
              def paintEvent(self, e):
                  painter = QtGui.QPainter()
                  painter.begin(self)
                  dial = QtGui.QPixmap("bg.png")
           
                  painter.setRenderHint(painter.Antialiasing)
                  rect = e.rect()
           
                  gauge_rect = QtCore.QRect(rect)
                  size = gauge_rect.size()
                  pos = gauge_rect.center()
                  gauge_rect.moveCenter( QtCore.QPoint(pos.x()-size.width(), pos.y()-size.height()) )
                  gauge_rect.setSize(size*.9)
                  gauge_rect.moveCenter(pos)
           
                  refill_rect = QtCore.QRect(gauge_rect)
                  size = refill_rect.size()
                  pos = refill_rect.center()
                  refill_rect.moveCenter( QtCore.QPoint(pos.x()-size.width(), pos.y()-size.height()) )
                  refill_rect.setSize(size*.9)
                  refill_rect.moveCenter(pos)
           
                  painter.setPen(QtCore.Qt.NoPen)
           
                  painter.drawPixmap(rect, dial)
           
                  painter.save()
                  grad = QtGui.QConicalGradient(QtCore.QPointF(gauge_rect.center()), 270.0)
                  grad.setColorAt(.75, QtCore.Qt.green)
                  grad.setColorAt(.5, QtCore.Qt.yellow)
                  grad.setColorAt(.1, QtCore.Qt.red)
                  painter.setBrush(grad)
                  painter.drawPie(gauge_rect, 225.0*16, -270*self.value*16)
                  painter.restore()
           
                  painter.setBrush(QtGui.QBrush(dial.scaled(rect.size())))
                  painter.drawEllipse(refill_rect)
           
                  super(QtGauge,self).paintEvent(e)   
                  painter.end()
           
           
          def main():
              app = QtGui.QApplication(sys.argv)
              ex = QtGauge()
              ex.setValue(0.6)
              print ex.getValue()
              sys.exit(app.exec_())
           
           
          if __name__ == '__main__':
              main()

          However, I recommend changing the background image itself because it’s more slick. If I get some more time today I may look into it deeper. I hope that helps 🙂