Qtimer и закрытие приложения по прошествии 15 секунд

Вечер. Мне немного сложно понять QTimer и то, как он работает, а также заставить работать приведенный ниже код. Как бы я не ненавидел копировать/вставлять, я просто не могу понять это. Цель этого состоит в том, чтобы запустить программу на 15 секунд, а затем полностью выйти. Все остальное работает, но когда я пытаюсь интегрировать QTimer для подсчета количества прошедших секунд, он ничего не делает или просто не работает независимо от того, какие варианты я пробовал. Ниже приведен последний код:

from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtGui import QMovie
from PyQt5.QtCore import QTimer
import winsound
import time 
import sys

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(321, 249)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.label = QtWidgets.QLabel(self.centralwidget)
        self.label.setGeometry(QtCore.QRect(0, 0, 320, 248))
        self.label.setFrameShape(QtWidgets.QFrame.Box)              
        self.label.setOpenExternalLinks(False)
        self.label.setTextInteractionFlags(QtCore.Qt.NoTextInteraction)
        self.label.setObjectName("label")
        MainWindow.setCentralWidget(self.centralwidget)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

        #Plays the movie in the Label
        movie = QMovie("giphy.gif")        
        self.label.setMovie(movie)
        movie.start()

        #Plays the sound with the movie
        winsound.PlaySound("magicwrd.wav", winsound.SND_ASYNC|winsound.SND_LOOP)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))


    #Borrowed and modified from here: https://stackoverflow.com/questions/46656634/pyqt5-qtimer-count-until-specific-seconds
    #Goal is to run the application for 15 seconds and then exit out completely. 
    def start_timer(self, slot, count=1, interval=1000):
        counter = 0
        def handler():
            nonlocal counter
            counter += 1
            slot(counter)
            if counter >= count:
                timer.stop()
                timer.deleteLater()
        timer = QtCore.QTimer()
        timer.timeout.connect(handler)
        timer.start(interval)

    def timer_func(self, count):
        if count >= 5:
            sys.exit(app.exec_())


if __name__ == "__main__":

    app = QtWidgets.QApplication(sys.argv)
    MainWindow = QtWidgets.QMainWindow()
    ui = Ui_MainWindow()
    ui.setupUi(MainWindow)
    MainWindow.show()
    Ui_MainWindow.start_timer(Ui_MainWindow.timer_func, 5)
    app.exec_()

person Nicholas    schedule 23.12.2019    source источник
comment
slot(counter) вызывает его выход. попробуйте прокомментировать это. в качестве окончательного решения вы должны попробовать асинхронно с ThreadEventLoop (quamash) для достижения вашего приложения для проигрывателя gif.   -  person oetzi    schedule 23.12.2019
comment
Этот код не является излишеством, это минимально воспроизводимый пример.   -  person eyllanesc    schedule 24.12.2019


Ответы (1)


Если вы хотите завершить приложение за T секунд, вы должны использовать QTimer::singleShot(), чтобы при его запуске вызывался QCoreApplication::quit():

QtCore.QTimer.singleShot(T * 1000, QtCore.QCoreApplication.quit)

В примере, на который вы ссылаетесь, у него есть другая цель: печатать некоторую информацию каждые T секунд, и после повторения K раз приложение закрывается и, следовательно, использует сложную логику, которая вам не нужна.

Принимая во внимание вышеизложенное и рекомендацию PyQt5, решение такое:

import sys
import winsound

from PyQt5 import QtCore, QtGui, QtWidgets


class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(321, 249)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.label = QtWidgets.QLabel(self.centralwidget)
        self.label.setGeometry(QtCore.QRect(0, 0, 320, 248))
        self.label.setFrameShape(QtWidgets.QFrame.Box)
        self.label.setOpenExternalLinks(False)
        self.label.setTextInteractionFlags(QtCore.Qt.NoTextInteraction)
        self.label.setObjectName("label")
        MainWindow.setCentralWidget(self.centralwidget)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))


class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        self.setupUi(self)
        # Plays the movie in the Label
        movie = QtGui.QMovie("giphy.gif")
        self.label.setMovie(movie)
        movie.start()
        # Plays the sound with the movie
        winsound.PlaySound("magicwrd.wav", winsound.SND_ASYNC | winsound.SND_LOOP)


if __name__ == "__main__":

    app = QtWidgets.QApplication(sys.argv)
    w = MainWindow()
    w.show()
    QtCore.QTimer.singleShot(15 * 1000, QtCore.QCoreApplication.quit)
    sys.exit(app.exec_())
person eyllanesc    schedule 23.12.2019
comment
Это работает! Спасибо! Я пытался использовать SingleShot, как было указано ранее, но я использовал его неправильно. - person Nicholas; 23.12.2019
comment
@Nicholas Если мой ответ помог вам, не забудьте отметить как правильный, если вы не знаете, как это сделать, проверьте тур - person eyllanesc; 23.12.2019
comment
@Nicholas Почему он стирает MRE? Вы также хотите стереть большую часть моего ответа. - person eyllanesc; 24.12.2019
comment
@Nicholas Не искажайте мой ответ, так как к вам могут быть применены санкции, и я отменю изменение. - person eyllanesc; 24.12.2019