vijayakumar_1 0 Newbie Poster

Iam designing a circular progress bar for my application. iam getting some example code which implements circular progress bar using PyQt4. I tried to convert the PyQt4 code in to PySide code which suits my application. but when i try to run the code iam getting error. plz help me in this regard.

Iam attaching my code below as well as the error iam getting

newpysidecircprogbar.py

from pysidecircularprogressbar import QRoundProgressBar
#from qroundprogressbar import QRoundProgressBar
import sys
from PySide.QtGui import *
from PySide import QtCore, QtGui

from time import sleep

class TstWidget(QtGui.QWidget):
    def __init__(self):
        super(type(self), self).__init__()

        self.bar = QRoundProgressBar()
        self.bar.setFixedSize(300, 300)

        self.bar.setDataPenWidth(3)
        self.bar.setOutlinePenWidth(3)
        self.bar.setDecimals(1)
        self.bar.setFormat('%v | %p %')
        # self.bar.resetFormat()
        self.bar.setNullPosition(90)
        self.bar.setBarStyle(QRoundProgressBar.StyleDonut)
        self.bar.setDataColors([(0., QtGui.QColor.fromRgb(255,0,0)), (0.5, QtGui.QColor.fromRgb(255,255,0)), (1., QtGui.QColor.fromRgb(0,255,0))])
        self.bar.setMaximun(100)
        self.bar.setMinimun(0)
        self.bar.setRange(0, 100)
        self.bar.setValue(0)

        button = QtGui.QPushButton("Start", self)

        button.clicked.connect(self.on_start)

        lay = QtGui.QVBoxLayout()
        lay.addWidget(button)
        lay.addWidget(self.bar)
        self.setLayout(lay)

        self.myLongTask = TaskThread()
        self.myLongTask.notifyProgress.connect(self.on_progress)

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

    def on_progress(self, i):
        self.bar.setValue(i)

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

   def run(self):
       for i in range(101):
           self.notifyProgress.emit(i)
           sleep(0.1)

def main():

    app = QtGui.QApplication(sys.argv)
    ex = TstWidget()
    ex.show()

    sys.exit(app.exec_())

if __name__ == '__main__':
    main()

pysideroundprogressbar.py

from PySide import QtCore, QtGui
class QRoundProgressBar(QtGui.QWidget):
StyleDonut = 1
StylePie = 2
StyleLine = 3

PositionLeft = 180
PositionTop = 90
PositionRight = 0
PositionBottom = -90

UF_VALUE = 1
UF_PERCENT = 2
UF_MAX = 4

def __init__(self):
    super(QRoundProgressBar, self).__init__()
    self.min = 0
    self.max = 100
    self.value = 25

    self.nullPosition = self.PositionTop
    self.barStyle = self.StyleDonut
    self.outlinePenWidth =1
    self.dataPenWidth = 1
    self.rebuildBrush = False
    self.format = "%p%"
    self.decimals = 1
    self.updateFlags = self.UF_PERCENT
    self.gradientData = []
    self.donutThicknessRatio = 0.75

def setRange(self, min, max):
    self.min = min
    self.max = max

    if self.max < self.min:
        self.max, self.min = self.min, self.max

    if self.value < self.min:
        self.value = self.min
    elif self.value > self.max:
        self.value = self.max

    if not self.gradientData:
        self.rebuildBrush = True
    self.update()

def setMinimun(self, min):
    self.setRange(min, self.max)

def setMaximun(self, max):
    self.setRange(self.min, max)

def setValue(self, val):
    if self.value != val:
        if val < self.min:
            self.value = self.min
        elif val > self.max:
            self.value = self.max
        else:
            self.value = val
        self.update()

def setNullPosition(self, position):
    if position != self.nullPosition:
        self.nullPosition = position
        if not self.gradientData:
            self.rebuildBrush = True
        self.update()

def setBarStyle(self, style):
    if style != self.barStyle:
        self.barStyle = style
        self.update()

def setOutlinePenWidth(self, penWidth):
    if penWidth != self.outlinePenWidth:
        self.outlinePenWidth = penWidth
        self.update()

def setDataPenWidth(self, penWidth):
    if penWidth != self.dataPenWidth:
        self.dataPenWidth = penWidth
        self.update()

def setDataColors(self, stopPoints):
    if stopPoints != self.gradientData:
        self.gradientData = stopPoints
        self.rebuildBrush = True
        self.update()

def setFormat(self, format):
    if format != self.format:
        self.format = format
        self.valueFormatChanged()

def resetFormat(self):
    self.format = ''
    self.valueFormatChanged()

def setDecimals(self, count):
    if count >= 0 and count != self.decimals:
        self.decimals = count
        self.valueFormatChanged()

def setDonutThicknessRatio(self, val):
    self.donutThicknessRatio = max(0., min(val, 1.))
    self.update()

def paintEvent(self, event):
    outerRadius = min(self.width(), self.height())
    baseRect = QtCore.QRectF(1, 1, outerRadius-2, outerRadius-2)

    buffer = QtGui.QImage(outerRadius, outerRadius, QtGui.QImage.Format_ARGB32)
    buffer.fill(0)

    p = QtGui.QPainter(buffer)
    p.setRenderHint(QtGui.QPainter.Antialiasing)

    # data brush
    self.rebuildDataBrushIfNeeded()

    # background
    self.drawBackground(p, buffer.rect())

    # base circle
    self.drawBase(p, baseRect)

    # data circle
    arcStep = 360.0 / (self.max - self.min) * self.value
    self.drawValue(p, baseRect, self.value, arcStep)

    # center circle
    innerRect, innerRadius = self.calculateInnerRect(baseRect, outerRadius)
    self.drawInnerBackground(p, innerRect)

    # text
    self.drawText(p, innerRect, innerRadius, self.value)

    # finally draw the bar
    p.end()

    painter = QtGui.QPainter(self)
    painter.drawImage(0, 0, buffer)

def drawBackground(self, p, baseRect):
    p.fillRect(baseRect, self.palette().background())

def drawBase(self, p, baseRect):
    bs = self.barStyle
    if bs == self.StyleDonut:
        p.setPen(QtGui.QPen(self.palette().shadow().color(), self.outlinePenWidth))
        p.setBrush(self.palette().base())
        p.drawEllipse(baseRect)
    elif bs == self.StylePie:
        p.setPen(QtGui.QPen(self.palette().base().color(), self.outlinePenWidth))
        p.setBrush(self.palette().base())
        p.drawEllipse(baseRect)
    elif bs == self.StyleLine:
        p.setPen(QtGui.QPen(self.palette().base().color(), self.outlinePenWidth))
        p.setBrush(Qt.Qt.NoBrush)
        p.drawEllipse(baseRect.adjusted(self.outlinePenWidth/2, self.outlinePenWidth/2, -self.outlinePenWidth/2, -self.outlinePenWidth/2))

def drawValue(self, p, baseRect, value, arcLength):
    # nothing to draw
    if value == self.min:
        return

    # for Line style
    if self.barStyle == self.StyleLine:
        p.setPen(QtGui.QPen(self.palette().highlight().color(), self.dataPenWidth))
        p.setBrush(Qt.Qt.NoBrush)
        p.drawArc(baseRect.adjusted(self.outlinePenWidth/2, self.outlinePenWidth/2, -self.outlinePenWidth/2, -self.outlinePenWidth/2),
                  self.nullPosition * 16,
                  -arcLength * 16)
        return

    # for Pie and Donut styles
    dataPath = QtGui.QPainterPath()
    dataPath.setFillRule(Qt.Qt.WindingFill)

    # pie segment outer
    dataPath.moveTo(baseRect.center())
    dataPath.arcTo(baseRect, self.nullPosition, -arcLength)
    dataPath.lineTo(baseRect.center())

    p.setBrush(self.palette().highlight())
    p.setPen(QtGui.QPen(self.palette().shadow().color(), self.dataPenWidth))
    p.drawPath(dataPath)

def calculateInnerRect(self, baseRect, outerRadius):
    # for Line style
    if self.barStyle == self.StyleLine:
        innerRadius = outerRadius - self.outlinePenWidth
    else:    # for Pie and Donut styles
        innerRadius = outerRadius * self.donutThicknessRatio

    delta = (outerRadius - innerRadius) / 2.
    innerRect = QtCore.QRectF(delta, delta, innerRadius, innerRadius)
    return innerRect, innerRadius

def drawInnerBackground(self, p, innerRect):
    if self.barStyle == self.StyleDonut:
        p.setBrush(self.palette().alternateBase())

        cmod = p.compositionMode()
        p.setCompositionMode(QtGui.QPainter.CompositionMode_Source)

        p.drawEllipse(innerRect)

        p.setCompositionMode(cmod)

def drawText(self, p, innerRect, innerRadius, value):
    if not self.format:
        return

    text = self.valueToText(value)

    # !!! to revise
    f = self.font()
    # f.setPixelSize(innerRadius * max(0.05, (0.35 - self.decimals * 0.08)))
    f.setPixelSize(innerRadius * 1.8 / len(text))
    p.setFont(f)

    textRect = innerRect
    p.setPen(self.palette().text().color())
    p.drawText(textRect, Qt.Qt.AlignCenter, text)

def valueToText(self, value):
    textToDraw = self.format

    format_string = '{' + ':.{}f'.format(self.decimals) + '}'

    if self.updateFlags & self.UF_VALUE:
        textToDraw = textToDraw.replace("%v", format_string.format(value))

    if self.updateFlags & self.UF_PERCENT:
        percent = (value - self.min) / (self.max - self.min) * 100.0
        textToDraw = textToDraw.replace("%p", format_string.format(percent))

    if self.updateFlags & self.UF_MAX:
        m = self.max - self.min + 1
        textToDraw = textToDraw.replace("%m", format_string.format(m))

    return textToDraw

def valueFormatChanged(self):
    self.updateFlags = 0;

    if "%v" in self.format:
        self.updateFlags |= self.UF_VALUE

    if "%p" in self.format:
        self.updateFlags |= self.UF_PERCENT

    if "%m" in self.format:
        self.updateFlags |= self.UF_MAX

    self.update()

def rebuildDataBrushIfNeeded(self):
    if self.rebuildBrush:
        self.rebuildBrush = False

        dataBrush = QtGui.QConicalGradient()
        dataBrush.setCenter(0.5,0.5)
        dataBrush.setCoordinateMode(QtGui.QGradient.StretchToDeviceMode)

        for pos, color in self.gradientData:
            dataBrush.setColorAt(1.0 - pos, color)

        # angle
        dataBrush.setAngle(self.nullPosition)

        p = self.palette()
        p.setBrush(QtGui.QPalette.Highlight, dataBrush)
        self.setPalette(p)

This the error iam getting

Traceback (most recent call last):
File "C:\Python27\newpysidecircprogbar.py", line 50, in
class TaskThread(QtCore.QThread):
File "C:\Python27\newpysidecircprogbar.py", line 52, in TaskThread
QtCore.Signal = QtCore.pyqtSignal(int)
AttributeError: 'module' object has no attribute 'pyqtSignal'

Dani AI

Generated

For — the traceback shows the classic PyQt→PySide naming clash: PySide does not expose PyQt’s pyqtSignal. In PySide the “new-style” signals are declared with QtCore.Signal (and slots with QtCore.Slot), so replace the class-level signal declaration with the PySide form. See the Qt Wiki for the PySide signal/slot guidance: Signals and Slots in PySide. (wiki.qt.io)

A minimal corrected pattern for your worker thread (only showing the signal/emit part) looks like this:

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

    def run(self):
        for i in range(101):
            self.notifyProgress.emit(i)
            time.sleep(0.1)

You can keep your existing myLongTask.notifyProgress.connect(self.on_progress) connection. If you need to keep code compatible with both PyQt and PySide during a port, you can alias the names at import time (for example QtCore.pyqtSignal = QtCore.Signal or from PySide.QtCore import Signal as pyqtSignal) — the Qt Wiki documents these portability options. (wiki.qt.io)

A couple of extra practical checks that often trip people when porting PyQt→PySide: on Python 2 use super(TstWidget, self).__init__() (calling super(type(self), self) is an anti-pattern and can break), and make sure QThreads are properly stopped and .wait()ed before application exit to avoid “QThread: Destroyed while thread is still running” crashes. See the Python super guidance and the PySide/PyQt differences notes for those points. (docs.quantifiedcode.com)

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.