расширить размер QPaintDevice после его инициализации - PullRequest
1 голос
/ 11 июня 2019

Немного контекста

Я пытаюсь сделать QSplashScreen с пользовательской анимацией.Я перепробовал много разных подходов, с каждым провалом.Главным образом, моей основной техникой было создание нового класса, который наследуется от QSplashScreen, а затем планируется с paintEvent().Это сработало ... иш.Анимация не проблема, это действительно QPaintDevice, который кажется поврежденным.

Поскольку я вызывал super(classname, self).__init__(args) единственный способ в моем init и передавал ему аргументы, которые я изменил в init, у меня всегда были поврежденные пиксели;Изображение было в странных тонах и имело линии разноцветных пикселей на заднем плане.Иногда это шаблоны, иногда они совершенно случайны.

enter image description here

Я пытался изменить каждую строку кода, и единственное, что удалило эти строки, это вызов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 Ответ

1 голос
/ 12 июня 2019

Проблема в том, что 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)
...