подпроцесс Popen, блокирующий PyQt GUI - PullRequest
1 голос
/ 10 апреля 2011

Я пытаюсь создать простой графический интерфейс для приложения конвертации видео под названием "HandBrake", используя PyQt.

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

Я не ищу более сложное решение, такое как индикатор выполнения и т. Д., Но я бы хотел просто отключить кнопку и изменить ее текст в ожидании завершения конвертации программы.

Как я могу сделать это с python & pyqt?

def videoProcess():
    self.pushButton.setEnabled(0)
    self.pushButton.setText("Please Wait")
    command = "handbrake.exe -i somefile.wmv -o somefile.mp4"
    p = subprocess.Popen(str(command), shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
    while 1:
        line = p.stdout.readline()
        if not line:
            self.pushButton.setEnabled(1)
            break

Ответы [ 2 ]

10 голосов
/ 11 апреля 2011

Поскольку вы уже в Qt land, вы можете сделать что-то вроде этого:

from PyQt4.QtCore import QProcess

class YourClass(QObject):

    [...]

    def videoProcess(self):
        self.pushButton.setEnabled(0)
        self.pushButton.setText("Please Wait")
        command = "handbrake.exe"
        args =  ["-i", "somefile.wmv", "-o", "somefile.mp4"]
        process = QProcess(self)
        process.finished.connect(self.onFinished)
        process.startDetached(command, args)

    def onFinished(self, exitCode, exitStatus):
        self.pushButton.setEnabled(True)

    [...]

http://doc.qt.io/qt-5/qprocess.html

1 голос
/ 10 апреля 2011

Если вам все равно не нужен вывод, вы можете использовать p.wait (), чтобы дождаться завершения подпроцесса, но вам все равно нужно вернуть управление в основной цикл QT, поэтому вам нужно вставить потоккак-то.Самое простое решение будет выглядеть примерно так:

import threading
def reenable():
    p.wait()
    self.pushButton.setEnabled(1)
t = threading.Thread(reenable)
t.run()

С этим связано множество нерешенных проблем.Например, допустимо ли вызывать действия GUI из нескольких потоков?Как насчет тайм-аута?Но этого должно быть достаточно, чтобы указать вам правильное направление.

...