初始化后扩大QPaintDevice的大小

expand the size of QPaintDevice after it is initialzed

一点背景

我正在尝试使用自定义动画制作 QSplashScreen。我尝试了很多不同的方法,每次都失败了。大多数情况下,我的主要技术是创建一个继承自 QSplashScreen 的新 Class,然后使用 paintEvent() 进行规划。它奏效了……是的。动画不是问题,它确实是似乎已损坏的 QPaintDevice。

因为我只是在我的 init 之后调用 super(classname, self).__init__(args) 并将我在 init 中修改的参数传递给它,所以我总是有损坏的像素;该图像色调怪异,背景中有彩色像素线。有时它是模式有时它是完全随机的。

我尝试更改每一行代码,唯一删除这些行的是在 __init__ 开头调用 super()。不幸的是,我正在制作一个要传递给 init 的框架。既然这是不可能的,我想修改我的 QSplashScreen 初始化的 QPaintDevice 的大小,因为我的动画显示在该帧之外。我不会 post 所有代码,因为自定义动画很重。

最小工作示例

from PyQt5.QtWidgets import QApplication, QSplashScreen, QMainWindow
from PyQt5.QtCore import Qt, QSize, pyqtSignal, QPoint
from PyQt5.QtGui import QPixmap, QPainter, QIcon, QBrush
import time, sys


class FakeAnimatedSplash(QSplashScreen):
    def __init__(self, image):
        self.image = image
        self.newFrame = QPixmap(self.image.size()+QSize(0, 20))
        super(FakeAnimatedSplash, self).__init__(self.newFrame, Qt.WindowStaysOnTopHint)

    def showEvent(self, event):
        self.update()

    def paintEvent(self, event):
        painter = QPainter(self)
        painter.fillRect(self.rect(), Qt.transparent)
        painter.setRenderHint(QPainter.Antialiasing, True)
        painter.setPen(Qt.NoPen)
        painter.drawPixmap(self.image.rect(), self.image)
        painter.drawEllipse(QPoint(0, 110), 8, 8)


class App(QApplication):
    def __init__(self, sys_argv):
        super(App, self).__init__(sys_argv)
        self.main = QMainWindow()
        self.setAttribute(Qt.AA_EnableHighDpiScaling)
        self.newSplash()
        self.main.show()

    def newSplash(self):
        pixmap = QPixmap("yourImage.png")
        smallerPixmap = pixmap.scaled(100, 100, Qt.KeepAspectRatio, Qt.SmoothTransformation)
        splash = FakeAnimatedSplash(smallerPixmap)
        splash.setEnabled(False)
        splash.show()
        start = time.time()
        while time.time() < start + 10:
            self.processEvents()


def main():
    app = App(sys.argv)
    app.setWindowIcon(QIcon("ABB_icon.png"))
    sys.exit(app.exec_())


if __name__ == '__main__':
    main()

可能的解决方案

super() 更改为开头使其工作但减少了隐藏我的动画的 QPaintDevice window。我想扩展它,但是初始化后没有方法可以做。

    def __init__(self, image):
        super(LoadingDotsSplash, self).__init__(image, QtCore.Qt.WindowStaysOnTopHint)
        self.image = image
        # here a function or method that changes the size of the QPaintDevice

问题在于 newFrame 是一个未初始化的 QPixmap,出于效率原因,像素未被修改,因此它们具有随机值,这是因为 FakeAnimatedSplash 的大小大于绘制的 QPixmap。解决方法是将newFrame像素的值设置为transparent:

class FakeAnimatedSplash(QSplashScreen):
    def __init__(self, image):
        self.image = image
        pix = QPixmap(self.image.size() + QSize(0, 20))
        pix.fill(Qt.transparent)
        super(FakeAnimatedSplash, self).__init__(pix, Qt.WindowStaysOnTopHint)

    def paintEvent(self, event):
        painter = QPainter(self)
        painter.fillRect(self.rect(), Qt.transparent)
        painter.setRenderHint(QPainter.Antialiasing, True)
        painter.setPen(Qt.NoPen)
        painter.drawPixmap(self.image.rect(), self.image)
        painter.drawEllipse(QPoint(0, 110), 8, 8)