Использование порта Radialbar QML с PyQt5 - PullRequest
0 голосов
/ 27 августа 2018

Я хочу использовать виджет «Radialbar» в эстетических целях в создаваемом мной графическом интерфейсе. В настоящее время я пытаюсь использовать порт, найденный в следующем месте:

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

Мой вопрос: как мне на самом деле использовать это в графическом интерфейсе, который я уже построил? В настоящее время я использую Qt Designer для создания файла пользовательского интерфейса, который я использую для графического интерфейса, а затем импортирую в PtQt5, используя:

    uic.loadUi("name.ui")

Есть ли способ включить этот виджет в мой существующий графический интерфейс? Я новичок в этом, и я не понимаю, как я должен использовать порт по ссылке выше.

1 Ответ

0 голосов
/ 28 августа 2018

Есть несколько вариантов:

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

Используя все вышеперечисленное, вы должны создать файл .py с именем radialbar.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, есть 2 варианта: создать плагин, который для новичка может быть тяжелым и ненужным, или продвигать его, этот второй метод - тот, который я собираюсь предложить.

Для этого в вашем дизайне необходимо добавить виджет:

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...