我有一个基本上是一个圆圈的小部件。我想逐步绘制它,所以我需要逐步绘制它(imo)。
通过下面的代码,我已经实现了我想要的。然而,有一个问题。我正在将 new 事件 传递给 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())
这一行产生了几个错误,但即使有这些错误,我也做了我想做的事。
如果我将
qevent
从函数本身传递给这个新调用,图像不会像我之前所说的那样更新。如果我创建这个新的
QPaintEvent
,它确实可以工作。但是,错误是:
Traceback (most recent call last):
File "/home/btc/Escritorio/SinestesiaRCB/Clases/Widget.py", line 68, in paintEvent self.paintEvent(QPaintEvent())
TypeError: arguments did not match any overloaded call: QPaintEvent(QRegion): not enough arguments
QPaintEvent(QRect): not enough arguments
QPaintEvent(QPaintEvent): not enough arguments
QBackingStore::endPaint() called with active painter on backingstore paint device
这些错误可能来自其他行,例如:
qevent.rect().x()
由于新事件是空的。
所以基本上我的问题是,我应该如何正确地做到这一点,这意味着实现我想要的而没有错误?
PS。我所说的渐进是什么意思。这已经创建了几个小部件,每个小部件在前一秒后创建。最佳答案
你不应该直接调用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_())
关于python - 使用pyqt5渐进绘画的正确方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53747154/