Загрузка анимации с проблемой зависания PyQt5 в процессе веб-автоматизации с помощью Selenium - PullRequest
1 голос
/ 07 мая 2020

Я работал над несколькими проектами веб-автоматизации. В этом примере я сократил свой код до открытия некоторых URL-адресов. Я хочу добавить удобный интерфейс, пока основной процесс продолжался. Однако, когда я хочу показать пользователю загрузку gif, он просто зависает из-за процесса селена. Если процесс селена завершен, время отдыха gif продолжается. Например, моя загрузка gif установлена ​​на 20 секунд. Процесс селена занял 5 секунд. Итак, в течение 5 секунд моя загрузка gif зависает, затем процесс селена завершается и закрывается, анимация загрузки gif продолжается 14 секунд.

Также есть способ сделать это с наложением. Я искал несколько примеров и пробовал, но это не сработало

import sys
import time
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.chrome.options import Options
from PyQt5 import QtWidgets, QtGui, QtCore
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *

class LoadingScreen(QtWidgets.QWidget):
    def __init__(self):
        super().__init__()
        self.setFixedSize(200,200)
        self.setWindowFlags(Qt.WindowStaysOnTopHint | Qt.CustomizeWindowHint)

        self.label_animation = QLabel(self)
        self.movie = QMovie("loading.gif")
        self.label_animation.setMovie(self.movie)

        timer = QTimer(self)
        self.startAnimation()
        timer.singleShot(20000, self.stopAnimation)

        self.show()

    def startAnimation(self):
        self.movie.start()

    def stopAnimation(self):
        self.movie.stop()
        self.close()

class demo(QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("Loading Overlay with Selenium Problem")
        self.resize(500, 500)
        self.center()
        self.twitter_icon = QtWidgets.QLabel("")
        self.twitter_icon.setAlignment(Qt.AlignCenter)
        self.pixmap = QtGui.QPixmap("twitter.png")
        self.pixmap = self.pixmap.scaled(64, 64, Qt.KeepAspectRatio, Qt.FastTransformation)
        self.twitter_icon.setPixmap(self.pixmap)
        self.twt_btn = QtWidgets.QPushButton("Twitter")

        v_box = QtWidgets.QVBoxLayout()
        v_box.addStretch()
        v_box.addWidget(self.twitter_icon)
        v_box.addWidget(self.twt_btn)
        v_box.addStretch()

        self.setLayout(v_box)

        self.twt_btn.clicked.connect(self.clkdBtn)
        self.show()

    def clkdBtn(self):
        self.hide()
        self.loading = LoadingScreen()
        browser = webdriver.Chrome()
        browser.get("https://twitter.com/login")
        time.sleep(1)
        #do more stuff in project instead i add more url
        browser.get("https://twitter.com/explore")
        time.sleep(1)
        browser.get("https://twitter.com/login")
        time.sleep(1)
        browser.close()
        time.sleep(1)
        self.show()

    def center(self):
        qr = self.frameGeometry()
        cp = QDesktopWidget().availableGeometry().center()
        qr.moveCenter(cp)
        self.move(qr.topLeft())

app = QApplication(sys.argv)
dm = demo()
app.exit((app.exec_()))

1 Ответ

2 голосов
/ 07 мая 2020

Вы не должны реализовывать трудоемкие задачи (selenium и time.sleep ()) в основном потоке, поскольку они блокируют GUI, поэтому вы должны запустить эту часть в другом потоке и уведомить GUI с помощью сигналов для изменения его состояние (показать или скрыть windows)

import sys
import threading
import time

from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.chrome.options import Options

from PyQt5 import QtWidgets, QtGui, QtCore


class SeleniumManager(QtCore.QObject):
    started = QtCore.pyqtSignal()
    finished = QtCore.pyqtSignal()

    def start(self):
        threading.Thread(target=self._execute, daemon=True).start()

    def _execute(self):
        self.started.emit()
        browser = webdriver.Chrome()
        browser.get("https://twitter.com/login")
        time.sleep(1)
        # do more stuff in project instead i add more url
        browser.get("https://twitter.com/explore")
        time.sleep(1)
        browser.get("https://twitter.com/login")
        time.sleep(1)
        browser.close()
        time.sleep(1)
        self.finished.emit()


class LoadingScreen(QtWidgets.QWidget):
    def __init__(self):
        super().__init__()
        self.setFixedSize(200, 200)
        self.setWindowFlags(
            QtCore.Qt.WindowStaysOnTopHint | QtCore.Qt.CustomizeWindowHint
        )

        self.label_animation = QtWidgets.QLabel(self)
        self.movie = QtGui.QMovie("loading.gif")
        self.label_animation.setMovie(self.movie)

    def startAnimation(self):
        self.movie.start()
        self.show()
        QtCore.QTimer.singleShot(2 * 1000, self.stopAnimation)

    def stopAnimation(self):
        self.movie.stop()
        self.hide()


class Demo(QtWidgets.QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("Loading Overlay with Selenium Problem")
        self.resize(500, 500)
        self.center()
        self.twitter_icon = QtWidgets.QLabel("")
        self.twitter_icon.setAlignment(QtCore.Qt.AlignCenter)
        self.pixmap = QtGui.QPixmap("twitter.png")
        self.pixmap = self.pixmap.scaled(
            64, 64, QtCore.Qt.KeepAspectRatio, QtCore.Qt.FastTransformation
        )
        self.twitter_icon.setPixmap(self.pixmap)
        self.twt_btn = QtWidgets.QPushButton("Twitter")

        v_box = QtWidgets.QVBoxLayout(self)
        v_box.addStretch()
        v_box.addWidget(self.twitter_icon)
        v_box.addWidget(self.twt_btn)
        v_box.addStretch()

        self.loading = LoadingScreen()
        self._manager = SeleniumManager()

        self._manager.started.connect(self.loading.startAnimation)
        self._manager.finished.connect(self.loading.stopAnimation)
        self.twt_btn.clicked.connect(self._manager.start)
        self._manager.started.connect(self.hide)
        self._manager.finished.connect(self.show)

    def center(self):
        qr = self.frameGeometry()
        cp = QtWidgets.QDesktopWidget().availableGeometry().center()
        qr.moveCenter(cp)
        self.move(qr.topLeft())


if __name__ == "__main__":

    app = QtWidgets.QApplication(sys.argv)
    dm = Demo()
    dm.show()
    app.exit((app.exec_()))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...