PyQt изменить размер QMovie с помощью правильного сглаживания - PullRequest
0 голосов
/ 03 мая 2018

Я создал QLabel и установил его фильм на объект QMovie с анимированным GIF. Затем в resizeEvent моего приложения я изменяю размер и перемещаю метку, чтобы она была отцентрирована / подогнана под макет. Это прекрасно работает, но в фильме есть много тонких линий, которые полностью искажаются в операции изменения размера, кажется, что нет сглаживания. Так что либо я использую неправильный метод изменения размера, либо мне нужно где-то правильно установить сглаживание? В документации QMovie или QLabel нет ничего, что подсказывало бы, как это сделать. Я читал, что QMovie унаследован от QImageReader, хотя у него тоже нет свойства сглаживания, которое я мог бы найти.

EDIT

Я действительно заставил это работать, но это все еще не совсем правильно. Я обнаружил, что в QMovie есть метод setScaledSize, который фактически масштабирует базовый QImageViewer. Тогда я просто настраиваю ярлык на его содержание, а именно на фильм. Используя следующий код, я могу изменить размер фильма с помощью правильного сглаживания, однако он довольно «нервный» и «мерцающий» во время изменения размера, поэтому, очевидно, я делаю это не совсем «правильно». Также иногда он как-то теряет соотношение сторон. Все еще ищите правильный способ сделать это ... Может, QLabel - неправильный путь?

Вот рабочий пример

import sys
from PyQt4 import QtGui

class MovieTest(QtGui.QDialog):
    def __init__(self):
        super(MovieTest, self).__init__()

        layout = QtGui.QVBoxLayout()
        self.setLayout(layout)

        self.loading_lbl = QtGui.QLabel()
        self.loading_lbl.setSizePolicy(QtGui.QSizePolicy.Ignored, QtGui.QSizePolicyIgnored)
        self.loading_lbl.setScaledContents(True)
        layout.addWidget(self.loading_lbl)
        loading_movie = QtGui.QMovie("loading-radial_loop.gif") # some gif in here
        self.loading_lbl.setMovie(loading_movie)
        loading_movie.start()

        self.setGeometry(50,50,100,100)
        self.setMinimumSize(10,10)

    def resizeEvent(self, event):
        rect = self.geometry()
        size = min(rect.width(), rect.height())
        movie = self.loading_lbl.movie()
        movie.setScaledSize(QtCore.QSize(size, size))
        self.loading_lbl.adjustSize()

def main():
    app = QtGui.QApplication(sys.argv)
    ex = MovieTest()
    ex.show()
    sys.exit(app.exec_())

if __name__ == "__main__":
    main()

1 Ответ

0 голосов
/ 04 мая 2018

Хорошо, теперь я понял это, всего лишь несколько настроек кода в моем отредактированном посте. Секрет заключается в том, чтобы сохранить метку в полном размере родительского прямоугольника (в данном случае размер всего макета), а затем масштабировать фильм внутри метки. По сути, вы внутренне масштабируете фильм, вместо того, чтобы он автоматически заполнял содержимое метки. Из того, что я могу сказать, это немного меняет порядок операций и позволяет фильму масштабировать себя при рендеринге вместо рендеринга кадра, а затем масштабировать его до размера метки.

Рабочий код:

import sys
from PyQt4 import QtGui, QtCore

class MovieTest(QtGui.QDialog):
    def __init__(self):
        super(MovieTest, self).__init__()

        layout = QtGui.QVBoxLayout()
        self.setLayout(layout)

        self.loading_lbl = QtGui.QLabel()
        self.loading_lbl.setStyleSheet('border: 1px solid red') # just for illustration
        self.loading_lbl.setAlignment(QtCore.Qt.AlignCenter)
        layout.addWidget(self.loading_lbl)
        loading_movie = QtGui.QMovie("loading-radial_loop.gif")
        self.loading_lbl.setMovie(loading_movie)
        loading_movie.start()

        self.setGeometry(50,50,100,100)
        self.setMinimumSize(10,10)

    def resizeEvent(self, event):
        rect = self.geometry()
        size = QtCore.QSize(min(rect.width(), rect.height()), min(rect.width(), rect.height()))

        movie = self.loading_lbl.movie()
        movie.setScaledSize(size)

def main():
    app = QtGui.QApplication(sys.argv)
    ex = MovieTest()
    ex.show()
    sys.exit(app.exec_())

if __name__ == "__main__":
    main()
...