2 回答

TA贡献1852条经验 获得超1个赞
您的描述与您的代码不符,也不符合正确的逻辑。
作为 GUI 一部分的 gif 必须在主线程(GUI 线程)中执行,而繁重的任务则在辅助线程中执行。
不要在主线程中使用 time.sleep()。
它完成执行繁重的任务并不意味着它完成了 gif 的执行,您必须停止它。
考虑到上述情况,一种更简单的方法是创建一个存在于另一个线程中的 QObject 并在那里执行任务,这允许您添加启动和完成信号。
import os
import time
from functools import partial
from PyQt5 import QtCore, QtGui, QtWidgets, uic
current_dir = os.path.dirname(os.path.realpath(__file__))
def callback():
# emulate task
time.sleep(3.0)
class Worker(QtCore.QObject):
started = QtCore.pyqtSignal()
finished = QtCore.pyqtSignal()
@QtCore.pyqtSlot(object)
def task(self, fun):
self.started.emit()
fun()
self.finished.emit()
class Main(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(Main, self).__init__(parent)
filename = os.path.join(current_dir, "Test.ui")
uic.loadUi(filename, self)
self.Animacion.setScaledContents(True)
thread = QtCore.QThread(self)
thread.start()
self._worker = Worker()
self._worker.moveToThread(thread)
self._worker.started.connect(self.show_image)
self._worker.finished.connect(self.on_finished)
wrapper = partial(self._worker.task, callback)
self.Iniciar.clicked.connect(wrapper)
@QtCore.pyqtSlot()
def show_image(self):
_movie = QtGui.QMovie("Loader.gif")
self.Animacion.setMovie(_movie)
self.Animacion.movie().start()
@QtCore.pyqtSlot()
def on_finished(self):
self.tabWidget.setCurrentIndex(1)
self.Animacion.movie().stop()
def main():
import sys
app = QtWidgets.QApplication(sys.argv)
w = Main()
w.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()

TA贡献1966条经验 获得超4个赞
您使用了错误的线程,更好的方法是使用 Qt GUI 线程。stop()但是,除了使用orkill()方法(顺便说一句,它们不应该被设置为self._thread您定义的变量而不是TheThread类吗?)之外,我发现演示在 Python 中杀死线程的多种方法很好。这些技术本质上是骇人听闻的,但它们确实有效。
首先,您可以抛出异常,因为异常总是会阻止代码执行。此示例使用该ctypes库:
import ctypes
def get_id(self):
# returns id of the respective thread
if hasattr(self, '_thread_id'):
return self._thread_id
for id, thread in threading._active.items():
if thread is self:
return id
def raise_exception(self):
thread_id = self.get_id()
res = ctypes.pythonapi.PyThreadState_SetAsyncExc(thread_id,
ctypes.py_object(SystemExit))
if res > 1:
ctypes.pythonapi.PyThreadState_SetAsyncExc(thread_id, 0)
print('Exception raise failure')
self._thread.raise_exception();
您还可以使用布尔标志变量,当设置为 true 时,执行一个break语句,结束程序。您可以在run()函数中定义线程,然后该join()方法基本上停止线程:
def run():
while True:
global stop_threads
if stop_threads:
break
self._thread = threading.Thread(target = run)
self_thread.start()
stop_threads = True
self_thread.join()
您还可以使用多处理模块,而不是使用线程,您可以使用进程,这非常相似,唯一的区别是线程在相同的内存空间中运行,而进程具有单独的内存。该terminate()方法杀死进程:
import multiprocessing
import time
def func(number):
for i in range(1, 10):
time.sleep(0.01)
print('Processing ' + str(number) + ': prints ' + str(number*i))
all_processes = []
for i in range(0, 3):
process = multiprocessing.Process(target=func, args=(i,))
process.start()
all_processes.append(process)
# Kill all processes after 0.03s
time.sleep(0.03)
for process in all_processes:
process.terminate()
最后,您可以通过将线程设置为守护进程来终止该线程。默认情况下,线程不会在程序结束时结束,所以守护线程是那些在主程序退出时被杀死的线程:
def func():
while True:
time.sleep(0.5)
print('Thread alive, but it will die on program termination')
self._thread = threading.Thread(target=func)
self._thread.daemon = True
self._thread.start()
time.sleep(2)
sys.exit()
添加回答
举报