Зависает GUI во время выполнения функции
Есть программа, которая по нажатию на кнопку создаёт .GIF из .jpeg изображений в заданную директорию.
Во время выполнения функции make_gif() программа завивает до момента, пока не отработает функция.
Как убрать это зависание?
class Ui_Program(object):
def setupUi(self, Program):
Program.setObjectName("Program")
Program.resize(298, 99)
self.centralwidget = QtWidgets.QWidget(Program)
self.centralwidget.setObjectName("centralwidget")
self.filePath = QtWidgets.QLineEdit(self.centralwidget)
self.filePath.setGeometry(QtCore.QRect(10, 10, 281, 31))
font = QtGui.QFont()
font.setPointSize(10)
font.setBold(True)
font.setWeight(75)
self.filePath.setFont(font)
self.filePath.setStyleSheet("")
self.filePath.setText("")
self.filePath.setObjectName("filePath")
self.convert = QtWidgets.QPushButton(self.centralwidget)
self.convert.setGeometry(QtCore.QRect(30, 50, 241, 31))
font = QtGui.QFont()
font.setPointSize(14)
self.convert.setFont(font)
self.convert.setStyleSheet("QPushButton {\n"
" border-style: outset;\n"
" border: 1px solid gray;\n"
" border-width: 1px;\n"
" border-radius: 10px;\n"
" background-color: rgb(227, 227, 227);\n"
"}\n"
"QPushButton:pressed {\n"
" background-color: rgb(203, 203, 203);\n"
"}\n"
"")
self.convert.setObjectName("btn")
self.statusLabel = QtWidgets.QLabel(self.centralwidget)
self.statusLabel.setGeometry(QtCore.QRect(10, 130, 241, 31))
font = QtGui.QFont()
font.setPointSize(14)
self.statusLabel.setFont(font)
self.statusLabel.setText("")
self.statusLabel.setObjectName("statusLabel")
Program.setCentralWidget(self.centralwidget)
self.retranslateUi(Program)
QtCore.QMetaObject.connectSlotsByName(Program)
def retranslateUi(self, Program):
_translate = QtCore.QCoreApplication.translate
Program.setWindowTitle(_translate("Program", "MainWindow"))
self.convert.setText(_translate("Program", "CONVERT"))
class MainWindow(QMainWindow, Ui_Program):
def __init__(self):
super(MainWindow, self).__init__()
self.ui = Ui_Program()
self.ui.setupUi(self)
self.ui.convert.clicked.connect(lambda: self.make_gif(self.filePath.text()))
def make_gif(self, file_path):
images = glob.glob(f"frames/*.jpg")
images.sort()
frames = [Image.open(image) for image in images]
frame_one = frames[0]
frame_one.save(f"{file_path}/example.gif", format="GIF", append_images=frames, save_all=True, duration=40, loop=0)
if __name__ == '__main__':
app = QApplication([])
window = MainWindow()
window.show()
app.exec_()
Ответы (1 шт):
Автор решения: S. Nick
→ Ссылка
Если ваша программа завивает, значит какие-то выполняемые операции тяжелые и должны выполняться в дополнительном потоке. Как вариант, это может выглядеть примерно так:
import sys
import glob
from PIL import Image
from PyQt5 import QtCore, QtWidgets, QtGui
from PyQt5.Qt import *
class Ui_Program(object):
def setupUi(self, Program):
Program.setObjectName("Program")
Program.resize(298, 99)
self.centralwidget = QtWidgets.QWidget(Program)
self.centralwidget.setObjectName("centralwidget")
self.filePath = QtWidgets.QLineEdit(self.centralwidget)
self.filePath.setGeometry(QtCore.QRect(10, 10, 281, 31))
font = QtGui.QFont()
font.setPointSize(10)
font.setBold(True)
font.setWeight(75)
self.filePath.setFont(font)
self.filePath.setStyleSheet("")
self.filePath.setText("")
self.filePath.setObjectName("filePath")
self.convert = QtWidgets.QPushButton(self.centralwidget)
self.convert.setGeometry(QtCore.QRect(30, 50, 241, 31))
font = QtGui.QFont()
font.setPointSize(14)
self.convert.setFont(font)
self.convert.setStyleSheet("QPushButton {\n"
" border-style: outset;\n"
" border: 1px solid gray;\n"
" border-width: 1px;\n"
" border-radius: 10px;\n"
" background-color: rgb(227, 227, 227);\n"
"}\n"
"QPushButton:pressed {\n"
" background-color: rgb(203, 203, 203);\n"
"}\n"
"")
self.convert.setObjectName("btn")
self.statusLabel = QtWidgets.QLabel(self.centralwidget)
self.statusLabel.setGeometry(QtCore.QRect(10, 130, 241, 31))
font = QtGui.QFont()
font.setPointSize(14)
self.statusLabel.setFont(font)
self.statusLabel.setText("")
self.statusLabel.setObjectName("statusLabel")
Program.setCentralWidget(self.centralwidget)
self.retranslateUi(Program)
QtCore.QMetaObject.connectSlotsByName(Program)
def retranslateUi(self, Program):
_translate = QtCore.QCoreApplication.translate
Program.setWindowTitle(_translate("Program", "MainWindow"))
self.convert.setText(_translate("Program", "CONVERT"))
# +++ vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
class Thread(QtCore.QThread):
finished = QtCore.pyqtSignal()
def __init__(self, parent=None):
super().__init__(parent)
self.file_path = None
def run(self):
images = glob.glob(f"frames/*.jpg")
images.sort()
frames = [Image.open(image) for image in images]
frame_one = frames[0]
frame_one.save(
f"{self.file_path}/example.gif",
format="GIF",
append_images=frames,
save_all=True,
duration=400,
loop=0
)
self.finished.emit()
# +++ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
class MainWindow(QMainWindow, Ui_Program):
def __init__(self):
super(MainWindow, self).__init__()
self.setupUi(self)
# ??? self.convert.clicked.connect(lambda: self.make_gif(self.filePath.text()))
self.convert.clicked.connect(self.make_gif)
layout = QtWidgets.QVBoxLayout(self.centralwidget)
layout.addWidget(self.filePath)
layout.addWidget(self.convert)
layout.addWidget(self.statusLabel, alignment=Qt.AlignCenter)
self.thread = Thread() # +++
self.thread.finished.connect(self._finished) # +++
# def make_gif(self, file_path):
def make_gif(self):
file_path = self.filePath.text()
if not file_path:
return
self.thread.file_path = self.filePath.text() # +++
self.thread.start() # +++
self.movie = QMovie("img/Fo2BxBK.gif") # установмте какую-нибудь свою
self.statusLabel.setMovie(self.movie)
self.movie.start()
def _finished(self):
self.movie.stop()
self.movie = QMovie(f"{self.filePath.text()}/example.gif")
self.statusLabel.setMovie(self.movie)
self.movie.setScaledSize(QSize(self.statusLabel.width(), self.statusLabel.height()))
self.movie.start()
if __name__ == '__main__':
app = QApplication([])
window = MainWindow()
window.show()
app.exec_()


