2015-11-06 65 views
0

有谁知道我可以在PyQt上实现圆形进度条吗?任何PyQt循环进度条?

另外,我发现已有代码: http://sourceforge.net/projects/qroundprogressbar/

但是,它是如何在C++中。如何使用它的PyQt?

更新:使用下面的QRoundProgressBar实现,我创建了一个完整的演示应用程序与开始按钮来演示QRoundProgressBar。 将QRoundProgressBar保存在circularprogressbar.py中,并在下面的代码的同一目录中创建一个新文件。希望它能帮助别人。

from circularprogressbar import QRoundProgressBar 
import sys 
from PyQt4.QtGui import * 
from PyQt4 import QtCore, QtGui, Qt 
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() 

enter image description here

+4

你有源代码,所以只需在pyqt中重写它 - 它只有几百行。 – ekhumoro

回答

4

我已经在PyQt的移植QRoundProgressBar(并修正了一些小错误):

from PyQt4 import QtCore, QtGui, Qt 

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().__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) 

用例:

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.setDonutThicknessRatio(0.85) 
     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.setRange(0, 300) 
     self.bar.setValue(260) 

     lay = QtGui.QVBoxLayout() 
     lay.addWidget(self.bar) 
     self.setLayout(lay) 
+0

谢谢。我在一个简单的应用程序上试了一下,效果很好。但是,我不知道如何更改0 | 0%到0 | 100%。例如,当进展正在进行时,它应该如下所示: 0 | 100% 1 | 100% ... 100 | 100% 而不是, 0 | 0% 1 | 0% ... 100 | 100% 如果读数准备剩余的百分比超出最大值,那么给出% – electro

+0

@electro'.setFormat('%p/100%')'? –

-2

我写这篇文章

class RoundProgress(QProgressBar): 
def __init__(self,parent): 
    QProgressBar.__init__(self) 
    self.values = self.value() 
    self.values = (self.values*360)/100 
    self.parent = parent 
    self.setParent(parent) 
    self.n = self.value() 
    self.label = QLabel("<center>100%<center>") 
    self.label.setStyleSheet("color:red;") 
    self.label.setFont(QFont("courrier",math.sqrt(self.width()))) 
    self.v = QVBoxLayout(self) 
    self.setLayout(self.v) 
    self.v.addWidget(self.label) 
def setValue(self,n): 
    self.n = n 
    self.values = ((n*5650)/100)*(-1) 
    self.label.setText("<center>"+str(self.n)+"</center>") 
def setNvalue(self,n): 
    self.n = n 
    self.values = ((n*5650)/100)*(-1) 
    self.label.setText("<center>"+str(self.n)+"</center>") 
def paintEvent(self,event): 
    painter = QPainter(self) 
    painter.setRenderHint(QPainter.Antialiasing) 
    pen = QPen() 
    pen.setWidth(2) 
    pen.setColor(QColor("darkblue")) 
    painter.setPen(pen) 
    pen = QPen() 
    pen.setWidth(9) 
    pen.setColor(QColor("lightgrey")) 
    painter.setPen(pen) 
    painter.drawArc(5.1,5.1,self.width()-10,self.height()-10,1450,-5650) 
    #painter.drawEllipse(0,0,100,100) 
    painter.setBrush(QColor("lightblue")) 
    pen = QPen() 
    pen.setWidth(10) 
    pen.setColor(QColor("red")) 
    painter.setPen(pen) 
    painter.drawArc(5.1,5.1,self.width()-10,self.height()-10,1450,self.values) 
    self.update() 
+1

请解释一下你的回答 – Mazz

+0

其简单的进度部件画 –

+0

显示这个,用法示例https://ghostbin.com/paste/z4n89 –