将Radialbar QML端口与PyQt5一起使用

时间:2018-08-27 20:28:17

标签: python python-3.x pyqt pyqt5

我想在我正在创建的GUI中出于美学目的使用“ Radialbar”小部件。当前,我正在尝试使用在以下位置找到的端口:

http://pyjuice.com/porting-radialbar-cqt-pyqt/

我的问题是,我实际上如何在已经构建的GUI中使用它?我目前使用Qt Designer创建用于GUI的ui文件,然后使用以下命令将其导入PtQt5:

    uic.loadUi("name.ui")

有没有办法将此小部件包含到我现有的GUI中?我对此很陌生,不了解如何使用上面的链接使用端口。

1 个答案:

答案 0 :(得分:1)

有几种选择:

1。转换为QWidget

对您来说,最简单的选择是将QQuickPaintedItem转换为QWidget,这样就避免了学习使用QML的知识,这对初学者来说并非易事。

为此,必须进行一些更改:

  • 在设置器中使用update()方法:

    @SOME_PROPERTY.setter
    def SOME_PROPERTY(self, type):
        ...
        self.SOME_PROPERTYChanged.emit()
        self.update() # <----
    
  • paint()方法更改为paintEvent()并创建QPainter,因为paintEvent()不提供任何内容。

    def paintEvent(self, event):
        painter = QtGui.QPainter(self)
        painter.save()      
        ...
    
  • 最后,QWidget没有setWidth()setHeight()方法,您必须使用resize()方法。

使用以上所有内容,您都必须创建一个名为radiusbar.py的.py文件。

radialbar.py

from PyQt5 import QtCore, QtGui, QtWidgets


class RadialBar(QtWidgets.QWidget):
    class DialType():
        FullDial = 0
        MinToMax = 1
        NoDial = 2

    sizeChanged = QtCore.pyqtSignal()
    startAngleChanged = QtCore.pyqtSignal()
    spanAngleChanged = QtCore.pyqtSignal()
    minValueChanged = QtCore.pyqtSignal()
    maxValueChanged = QtCore.pyqtSignal()
    valueChanged = QtCore.pyqtSignal()
    dialWidthChanged = QtCore.pyqtSignal()
    backgroundColorChanged = QtCore.pyqtSignal()
    foregroundColorChanged = QtCore.pyqtSignal()
    progressColorChanged = QtCore.pyqtSignal()
    textColorChanged = QtCore.pyqtSignal()
    suffixTextChanged = QtCore.pyqtSignal()
    showTextChanged = QtCore.pyqtSignal()
    penStyleChanged = QtCore.pyqtSignal()
    dialTypeChanged = QtCore.pyqtSignal()
    textFontChanged = QtCore.pyqtSignal()


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

        self.resize(200, 200)
        # self.setSmooth(True)
        # self.setAntialiasing(True)

        self._Size = 200
        self._StartAngle = 40
        self._SpanAngle = 280
        self._MinValue = 0
        self._MaxValue = 100
        self._Value = 50
        self._DialWidth = 15
        self._BackgroundColor = QtCore.Qt.transparent
        self._DialColor = QtGui.QColor(80,80,80)
        self._ProgressColor = QtGui.QColor(135,26,5)
        self._TextColor = QtGui.QColor(0, 0, 0)
        self._SuffixText = ""
        self._ShowText = True
        self._PenStyle = QtCore.Qt.FlatCap
        self._DialType = RadialBar.DialType.MinToMax
        self._TextFont = QtGui.QFont()

    def paintEvent(self, event):
        painter = QtGui.QPainter(self)
        painter.save() 
        r = min(self.width(), self.height())     
        rect = QtCore.QRectF(0, 0, r, r) #self.boundingRect()
        painter.setRenderHint(QtGui.QPainter.Antialiasing)
        pen = painter.pen()
        pen.setCapStyle(self._PenStyle)

        startAngle = -90 - self._StartAngle
        if RadialBar.DialType.FullDial != self._DialType:
            spanAngle = 0 - self._SpanAngle
        else:
            spanAngle = -360

        #Draw outer dial
        painter.save()
        pen.setWidth(self._DialWidth)
        pen.setColor(self._DialColor)
        painter.setPen(pen)
        offset = self._DialWidth / 2
        if self._DialType == RadialBar.DialType.MinToMax:
            painter.drawArc(rect.adjusted(offset, offset, -offset, -offset), startAngle * 16, spanAngle * 16)
        elif self._DialType == RadialBar.DialType.FullDial:
            painter.drawArc(rect.adjusted(offset, offset, -offset, -offset), -90 * 16, -360 * 16)
        else:
            pass
            #do not draw dial

        painter.restore()

        #Draw background
        painter.save()
        painter.setBrush(self._BackgroundColor)
        painter.setPen(self._BackgroundColor)
        inner = offset * 2
        painter.drawEllipse(rect.adjusted(inner, inner, -inner, -inner))
        painter.restore()

        #Draw progress text with suffix
        painter.save()
        painter.setFont(self._TextFont)
        pen.setColor(self._TextColor)
        painter.setPen(pen)
        if self._ShowText:
            painter.drawText(rect.adjusted(offset, offset, -offset, -offset), QtCore.Qt.AlignCenter,str(self._Value) + self._SuffixText)
        else:
            painter.drawText(rect.adjusted(offset, offset, -offset, -offset), QtCore.Qt.AlignCenter, self._SuffixText)
        painter.restore()

        #Draw progress bar
        painter.save()
        pen.setWidth(self._DialWidth)
        pen.setColor(self._ProgressColor)
        valueAngle = float(float(self._Value - self._MinValue)/float(self._MaxValue - self._MinValue)) * float(spanAngle)  #Map value to angle range
        painter.setPen(pen)
        painter.drawArc(rect.adjusted(offset, offset, -offset, -offset), startAngle * 16, valueAngle * 16)
        painter.restore()


    @QtCore.pyqtProperty(str, notify=sizeChanged)
    def size(self):
        return self._Size

    @size.setter
    def size(self, size):
        if self._Size == size:
            return
        self._Size = size
        self.sizeChanged.emit()
        self.update()

    @QtCore.pyqtProperty(int, notify=startAngleChanged)
    def startAngle(self):
        return self._StartAngle

    @startAngle.setter
    def startAngle(self, angle):
        if self._StartAngle == angle:
            return
        self._StartAngle = angle
        self.startAngleChanged.emit()
        self.update()

    @QtCore.pyqtProperty(int, notify=spanAngleChanged)
    def spanAngle(self):
        return self._SpanAngle

    @spanAngle.setter
    def spanAngle(self, angle):
        if self._SpanAngle == angle:
            return
        self._SpanAngle = angle
        self.spanAngleChanged.emit()
        self.update()

    @QtCore.pyqtProperty(int, notify=minValueChanged)
    def minValue(self):
        return self._MinValue

    @minValue.setter
    def minValue(self, value):
        if self._MinValue == value:
            return
        self._MinValue = value
        self.minValueChanged.emit()
        self.update()

    @QtCore.pyqtProperty(int, notify=maxValueChanged)
    def maxValue(self):
        return self._MaxValue

    @maxValue.setter
    def maxValue(self, value):
        if self._MaxValue == value:
            return
        self._MaxValue = value
        self.maxValueChanged.emit()
        self.update()

    @QtCore.pyqtProperty(float, notify=valueChanged)
    def value(self):
        return self._Value

    @value.setter
    def value(self, value):
        if self._Value == value:
            return
        self._Value = value
        self.valueChanged.emit()
        self.update()

    @QtCore.pyqtProperty(int, notify=dialWidthChanged)
    def dialWidth(self):
        return self._DialWidth

    @dialWidth.setter
    def dialWidth(self, width):
        if self._DialWidth == width:
            return
        self._DialWidth = width
        self.dialWidthChanged.emit()
        self.update()

    @QtCore.pyqtProperty(QtGui.QColor, notify=backgroundColorChanged)
    def backgroundColor(self):
        return self._BackgroundColor

    @backgroundColor.setter
    def backgroundColor(self, color):
        if self._BackgroundColor == color:
            return
        self._BackgroundColor = color
        self.backgroundColorChanged.emit()
        self.update()

    @QtCore.pyqtProperty(QtGui.QColor, notify=foregroundColorChanged)
    def foregroundColor(self):
        return self._ForegrounColor

    @foregroundColor.setter
    def foregroundColor(self, color):
        if self._DialColor == color:
            return
        self._DialColor = color
        self.foregroundColorChanged.emit()
        self.update()

    @QtCore.pyqtProperty(QtGui.QColor, notify=progressColorChanged)
    def progressColor(self):
        return self._ProgressColor

    @progressColor.setter
    def progressColor(self, color):
        if self._ProgressColor == color:
            return
        self._ProgressColor = color
        self.progressColorChanged.emit()
        self.update()

    @QtCore.pyqtProperty(QtGui.QColor, notify=textColorChanged)
    def textColor(self):
        return self._TextColor

    @textColor.setter
    def textColor(self, color):
        if self._TextColor == color:
            return
        self._TextColor = color
        self.textColorChanged.emit()  
        self.update()

    @QtCore.pyqtProperty(str, notify=suffixTextChanged)
    def suffixText(self):
        return self._SuffixText

    @suffixText.setter
    def suffixText(self, text):
        if self._SuffixText == text:
            return
        self._SuffixText = text
        self.suffixTextChanged.emit()
        self.update()

    @QtCore.pyqtProperty(str, notify=showTextChanged)
    def showText(self):
        return self._ShowText

    @showText.setter
    def showText(self, show):
        if self._ShowText == show:
            return
        self._ShowText = show
        self.update()

    @QtCore.pyqtProperty(QtCore.Qt.PenCapStyle, notify=penStyleChanged)
    def penStyle(self):
        return self._PenStyle

    @penStyle.setter
    def penStyle(self, style):
        if self._PenStyle == style:
            return
        self._PenStyle = style
        self.penStyleChanged.emit()
        self.update()

    @QtCore.pyqtProperty(int, notify=dialTypeChanged)
    def dialType(self):
        return self._DialType

    @dialType.setter
    def dialType(self, type):
        if self._DialType == type:
            return
        self._DialType = type
        self.dialTypeChanged.emit()
        self.update()

    @QtCore.pyqtProperty(QtGui.QFont, notify=textFontChanged)
    def textFont(self):
        return self._TextFont

    @textFont.setter
    def textFont(self, font):
        if self._TextFont == font:
            return
        self._TextFont = font
        self.textFontChanged.emit()
        self.update()


if __name__ == '__main__':
    import sys
    app = QtWidgets.QApplication(sys.argv)
    w = RadialBar()
    w.backgroundColor = QtGui.QColor("#1dc58f")
    w.foregroundColor = QtGui.QColor("#191a2f")
    w.dialWidth = 10
    w.spanAngle = 70
    w.textColor = QtGui.QColor("#FFFFFF")
    w.penStyle = QtCore.Qt.RoundCap
    w.dialType = RadialBar.DialType.FullDial
    w.suffixText = "%"
    timeline = QtCore.QTimeLine(10000, w)
    timeline.setFrameRange(0, 100)
    timeline.frameChanged.connect(lambda val: setattr(w, "value", val))
    timeline.start()
    w.show()
    sys.exit(app.exec_())

enter image description here

如果您想在Qt Designer中使用它,则有两种选择:创建一个对初学者来说可能既繁琐又不必要的插件,或者对其进行推广,这是我将要提出的第二种方法。

为此,您必须在设计中添加一个小部件:

enter image description here

enter image description here

然后右键单击窗口小部件所在的部分,然后单击“升级为..”,然后在对话框中显示RadialBar,如下所示:

enter image description here

然后按“添加”按钮,然后按“升级”按钮。

在上面生成的.ui是:

name.ui:

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>Form</class>
 <widget class="QWidget" name="Form">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>400</width>
    <height>300</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>Form</string>
  </property>
  <layout class="QVBoxLayout" name="verticalLayout">
   <item>
    <layout class="QHBoxLayout" name="horizontalLayout">
     <item>
      <widget class="QLineEdit" name="lineEdit"/>
     </item>
     <item>
      <widget class="QPushButton" name="pushButton">
       <property name="text">
        <string>PushButton</string>
       </property>
      </widget>
     </item>
    </layout>
   </item>
   <item>
    <widget class="RadialBar" name="widget" native="true"/>
   </item>
  </layout>
 </widget>
 <customwidgets>
  <customwidget>
   <class>RadialBar</class>
   <extends>QWidget</extends>
   <header>radialbar.h</header>
   <container>1</container>
  </customwidget>
 </customwidgets>
 <resources/>
 <connections/>
</ui>

最后,您使用您的.ui文件:

main.py

from PyQt5 import QtCore, QtGui, QtWidgets, uic

class Widget(QtWidgets.QWidget):
    def __init__(self):
        QtWidgets.QWidget.__init__(self)
        uic.loadUi("name.ui", self)


if __name__ == '__main__':
    import sys
    app = QtWidgets.QApplication(sys.argv)
    w = Widget()
    w.show()
    sys.exit(app.exec_())

enter image description here

您必须具有的结构如下:

├── main.py
├── name.ui
└── radialbar.py