初始化后扩大QPaintDevice的大小

时间:2019-06-11 20:25:22

标签: python pyqt splash-screen qpainter

一些上下文

我正在尝试使用自定义动画制作QSplashScreen。我尝试了许多不同的方法,每次失败。通常,我的主要技术是创建一个继承自QSplashScreen的新类,然后使用paintEvent()进行计划。它奏效了。动画不是问题,实际上是QPaintDevice似乎已损坏。

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

{{3}}

我尝试过更改每一行代码,唯一删除这些行的是在super()的开头调用__init__。不幸的是,我正在制作传递给init的框架。现在不可能了,我想修改QPaintDevice初始化的QSplashScreen的大小,因为我的动画显示在该帧之外。由于自定义动画非常繁琐,因此我不会发布所有代码。

最小工作示例

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窗口,该窗口隐藏了我的动画。我想扩展它,但是没有方法可以在初始化后完成。

    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

1 个答案:

答案 0 :(得分:1)

问题是newFrame是未初始化的QPixmap,并且出于效率原因,像素未进行修改,因此它们具有随机值,这是因为FakeAnimatedSplash的大小大于绘制的QPixmap。解决方案是将newFrame像素的值设置为透明:

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)