1

我一直在从事一些网络自动化项目。在这个示例中,我将代码缩减为基本上打开一些 URL。我想在主进程继续的同时添加一些用户友好的界面。但是,当我想向用户展示加载 gif 时,由于 selenium 过程,它只是冻结了。如果 selenium 过程完成,则 gif 的 gif 休息时间继续。例如,我的加载 gif 设置为 20 秒。硒过程耗时 5 秒。所以 5 秒,我的加载 gif 冻结,然后 selenium 过程完成并关闭,加载 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_()))
4

1 回答 1

3

您不应该在主线程中实现耗时的任务(selenium 和 time.sleep()),因为它们会阻塞 GUI,因此您应该在另一个线程中运行该部分并使用信号通知 GUI 以更改其状态(显示或隐藏窗口)

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_()))
于 2020-05-07T13:46:50.850 回答