PySide / PyQt: выполнение функций после загрузки графического интерфейса - PullRequest
0 голосов
/ 20 сентября 2018

Я создаю крошечный инструмент, который выполняет файловые операции при запуске сеанса.Чтобы убедиться, что у пользователя есть визуальная обратная связь, я хочу связать ее с индикатором выполнения.

Здесь я до сих пор:

import sys
import time
from PySide.QtGui import *


class ProgressWindowWidget(QWidget):
    def __init__(self, parent=None):
        super(ProgressWindowWidget, self).__init__()

        self.init_ui()

    def init_ui(self):
        self.setGeometry(500, 500, 600, 100)
        self.setWindowTitle('Progress')

        self.layout_ = QGridLayout()
        self.setLayout(self.layout_)

        self.progress_bar = QProgressBar()
        self.layout_.addWidget(self.progress_bar, 0, 0, 1, 1)

    def my_operations(self):
        print('do something 1')
        time.sleep(2)
        print('do something 2')
        time.sleep(2)
        print('do something 3')
        time.sleep(2)


def main():
    app = QApplication(sys.argv)
    progress_window = ProgressWindowWidget()
    progress_window.show()
    progress_window.my_operations()
    sys.exit(app.exec_())


if __name__ == '__main__':
    main()

Моя проблема в том, что my_operationsсначала выполняется, а затем загружается мой графический интерфейс.Я хотел бы выполнить my_operations только при загрузке индикатора выполнения, чтобы я мог его обновить.

Согласно this , он как-то связан с циклом exec_ main, но, очевидно, что-то здесь я не понимаю, потому что я звоню my_operations после show.

Излишне говорить, что я новичок.У кого-нибудь есть идея?Приветствия

1 Ответ

0 голосов
/ 20 сентября 2018

Каждый GUI живет в цикле событий, который позволяет вам обрабатывать события пользователя, ОС и т. Д., Такие как мышь, клавиатура и т. Д., Поэтому, если вы заблокируете эту обработку, GUI не будет обновлять свой статус,в вашем случае проблема вызвана time.sleep(), который блокирует, не давая GUI активировать состояние отображения окна.Итак, как основное правило: не используйте time.sleep() внутри основного потока графического интерфейса, я полагаю, что time.sleep() эмулирует задачу, которая занимает определенное время, для этого случая вы должны выполнить эту задачу из другого потока, и если вы хотитеобновить GUI, вы должны сделать это с помощью сигналов, это не должно быть сделано напрямую.

В следующем примере я буду использовать threading.Thread() для создания нового потока и сигнал для обновления GUI:

import sys
import time
import threading
from PySide import QtCore, QtGui


class ProgressWindowWidget(QtGui.QWidget):
    progressSignal = QtCore.Signal(int)

    def __init__(self, parent=None):
        super(ProgressWindowWidget, self).__init__()
        self.init_ui()

    def init_ui(self):
        self.setGeometry(500, 500, 600, 100)
        self.setWindowTitle('Progress')

        self.layout_ = QtGui.QGridLayout()
        self.setLayout(self.layout_)

        self.progress_bar = QtGui.QProgressBar()
        self.progressSignal.connect(self.progress_bar.setValue)
        self.layout_.addWidget(self.progress_bar, 0, 0, 1, 1)

    def my_operations(self):
        print('do something 1')
        time.sleep(2)
        self.progressSignal.emit(33)
        print('do something 2')
        time.sleep(2)
        self.progressSignal.emit(66)
        print('do something 3')
        time.sleep(2)
        self.progressSignal.emit(100)


def main():
    app = QtGui.QApplication(sys.argv)
    progress_window = ProgressWindowWidget()
    progress_window.show()
    t = threading.Thread(target=progress_window.my_operations)
    t.start()
    sys.exit(app.exec_())


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