Правильный способ рисовать постепенно с pyqt5 - PullRequest
0 голосов
/ 12 декабря 2018

У меня есть виджет, который в основном круг.Я хочу рисовать его постепенно, поэтому мне нужно рисовать его поэтапно (imo).

С помощью следующего кода я достиг того, чего хочу.Тем не менее, есть проблема.Я передаю новое событие в функцию paintEvent, потому что если я этого не сделаю, изображение не будет обновлено, пока все не будет завершено, поэтому я не добиваюсь ничего, что хотел.

Код виджета

import sys
import time
from PyQt5.QtCore import Qt, QRect
from PyQt5.QtWidgets import QApplication, QWidget, QCheckBox, QDesktopWidget

from PyQt5.QtGui import QPen, QPainter, QPaintEvent, QConicalGradient, QColor, QBrush

class Circle(QWidget):

    def __init__(self, size, color):
        super().__init__()

        self.loadingAngle = 0
        self.width = 0
        self.color = color
        self.pixmap_opacity = 1

        self.resize(size, size);
        self.center()

        self.initUI()

    def initUI(self):

        self.width = 15
        self.loadingAngle = 0
        self.show()

    def center(self):
        qr = self.frameGeometry()
        cp = QDesktopWidget().availableGeometry().center()
        qr.moveCenter(cp)
        self.move(qr.topLeft())

    def paintEvent(self, qevent):

        self.setWindowFlags(Qt.FramelessWindowHint)
        self.setAttribute(Qt.WA_TranslucentBackground)
        self.setStyleSheet("background:transparent;")

        drawingRect = QRect()
        drawingRect.setX(qevent.rect().x() + self.width)
        drawingRect.setY(qevent.rect().y() + self.width)
        drawingRect.setWidth(qevent.rect().width() - self.width * 2)
        drawingRect.setHeight(qevent.rect().height() - self.width * 2)

        painter = QPainter(self)
        painter.setRenderHint(QPainter.Antialiasing)

        gradient = QConicalGradient()
        gradient.setCenter(drawingRect.center())
        gradient.setAngle(90)
        gradient.setColorAt(1, QColor(0,0,0))
        gradient.setColorAt(0, QColor(self.color[0], self.color[1],self.color[2]))

        arcLengthApproximation = self.width + self.width / 3
        pen = QPen(QBrush(gradient), self.width)
        pen.setCapStyle(Qt.RoundCap)
        painter.setPen(pen)
        painter.drawArc(drawingRect, 90 * 16 - arcLengthApproximation, -self.loadingAngle * 16)
        #time.sleep(0.25)

        if self.loadingAngle < 360:
            self.loadingAngle += 1
            #self.paintEvent(QDrawEvent())
            self.paintEvent(QPaintEvent())

Проблемная строка

self.paintEvent(QPaintEvent())

Эта строка выдает несколько ошибок, но даже с ними я делаю то, что хочу.

  1. Если я передам qevent от самой функции этому новому вызову, изображение не будет обновлено, как я уже говорил.

  2. Если я создам этот новыйQPaintEvent, это работает.Однако ошибки:

Трассировка (последний последний вызов):

Файл "/ home / btc / Escritorio / SinestesiaRCB / Clases / Widget.py ", строка 68, в paintEvent self.paintEvent (QPaintEvent ())

TypeError: аргументы не соответствуют ни одному перегруженному вызову: QPaintEvent (QRegion): недостаточно аргументов

QPaintEvent (QRect): недостаточно аргументов

QPaintEvent (QPaintEvent): недостаточно аргументов

QBackingStore :: endPaint () вызывается активным художником на устройстве рисования backingstore

Эти ошибки могутисходить из других строк, например:

qevent.rect().x()

Поскольку новое событие пустое.

Поэтому в основном мой вопрос заключается в том, как мне сделать это, чтобы сделать его правильно, имея в виду добейся того, что я хочу без ошибок ?

PS.Что я имею в виду, постепенно.Это было сделано путем создания нескольких виджетов, по одной секунде после предыдущего.

enter image description here

1 Ответ

0 голосов
/ 12 декабря 2018

Вы никогда не должны вызывать paintEvent напрямую, вы должны использовать update() для его косвенного вызова.С другой стороны, если вы хотите, чтобы вас вызывали так часто, вам следует использовать QTimer или лучше QTimeLine в этом случае.

import sys
from PyQt5 import QtCore, QtGui, QtWidgets

class Circle(QtWidgets.QWidget):
    def __init__(self, size, color):
        super().__init__()
        self._loading_angle = 0
        self.width = 0
        self.color = color
        self.pixmap_opacity = 1
        self.resize(size, size)
        self.setWindowFlags(QtCore.Qt.FramelessWindowHint)
        self.setAttribute(QtCore.Qt.WA_TranslucentBackground)
        self.setStyleSheet("background:transparent;")
        self.center()
        self.initUI()

        timeline = QtCore.QTimeLine(4000, self)
        timeline.setFrameRange(0, 360)
        timeline.frameChanged.connect(self.setLoadingAngle)
        timeline.start()

    def initUI(self):
        self.width = 15
        self.setLoadingAngle(0)
        self.show()

    def loadingAngle(self):
        return self._loading_angle

    def setLoadingAngle(self, angle):
        self._loading_angle = angle
        self.update()

    loadingAngle = QtCore.pyqtProperty(int, fget=loadingAngle, fset=setLoadingAngle)

    def center(self):
        qr = self.frameGeometry()
        cp = QtWidgets.QDesktopWidget().availableGeometry().center()
        qr.moveCenter(cp)
        self.move(qr.topLeft())

    def paintEvent(self, event):
        painter = QtGui.QPainter(self)
        painter.setRenderHint(QtGui.QPainter.Antialiasing)
        drawingRect  = QtCore.QRect(QtCore.QPoint(), self.rect().size() - 2*self.width*QtCore.QSize(1, 1))
        drawingRect.moveCenter(self.rect().center())

        gradient = QtGui.QConicalGradient()
        gradient.setCenter(drawingRect.center())
        gradient.setAngle(90)
        gradient.setColorAt(1, QtGui.QColor(0,0,0))
        gradient.setColorAt(0, self.color)
        arcLengthApproximation = self.width + self.width / 3
        pen = QtGui.QPen(QtGui.QBrush(gradient), self.width)
        pen.setCapStyle(QtCore.Qt.RoundCap)
        painter.setPen(pen)
        painter.drawArc(drawingRect, 90 * 16 - arcLengthApproximation, -self._loading_angle * 16)


if __name__ == '__main__':
    import sys
    app = QtWidgets.QApplication(sys.argv)
    w = Circle(400, QtGui.QColor("blue"))
    w.show()
    sys.exit(app.exec_())
...