【python】pyqt5执行耗时网络请求,显示dialog完整代码

本文提供了一个使用PyQt5在执行网络请求时显示ProgressDialog的完整代码示例,涉及QDialog和QMainWindow的继承,模态对话框的使用,以及禁用其他部件的功能。

以下是一个使用PyQt5执行网络请求并在执行过程中显示一个执行中的对话框的完整代码示例:

一、继承QDialog实现

import sys
import requests
from PyQt5.QtWidgets import QApplication, QDialog, QLabel, QVBoxLayout
from PyQt5.QtCore import Qt, QThread, pyqtSignal


class RequestThread(QThread):
    finished = pyqtSignal(bool)

    def __init__(self, url):
        super().__init__()
        self.url = url

    def run(self):
        try:
            response = requests.get(self.url)
            if response.status_code == 200:
                self.finished.emit(True)
            else:
                self.finished.emit(False)
        except:
            self.finished.emit(False)


class ProgressDialog(QDialog):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setWindowTitle("执行中")
        self.setFixedSize(200, 100)
        self.setWindowFlags(Qt.CustomizeWindowHint | Qt.WindowTitleHint)
        layout = QVBoxLayout(self)
        self.label = QLabel("正在执行,请稍候...", self)
        layout.addWidget(self.label, alignment=Qt.AlignCenter)

    def setMessage(self, text):
        self.label.setText(text)


class MainWindow(QDialog):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("网络请求")
        self.setFixedSize(300, 100)
        layout = QVBoxLayout(self)
        self.label = QLabel("点击按钮执行网络请求", self)
        layout.addWidget(self.label, alignment=Qt.AlignCenter)
        self.button = QPushButton("执行请求", self)
        self.button.clicked.connect(self.executeRequest)
        layout.addWidget(self.button, alignment=Qt.AlignCenter)
        self.progressDialog = ProgressDialog(self)

    def executeRequest(self):
        url = "https://www.example.com"
        self.progressDialog.show()
        self.progressDialog.setMessage("正在执行网络请求,请稍候...")
        self.requestThread = RequestThread(url)
        self.requestThread.finished.connect(self.onRequestFinished)
        self.requestThread.start()

    def onRequestFinished(self, success):
        self.progressDialog.hide()
        if success:
            self.label.setText("网络请求执行成功")
        else:
            self.label.setText("网络请求执行失败")


if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec_())

在这个例子中,我们使用了PyQt5的QThread类来在后台执行网络请求,并使用pyqtSignal来在请求完成时向主线程发送信号。ProgressDialog是一个自定义的对话框,用于在执行请求时显示一个执行中的消息。MainWindow是我们的主窗口,包含一个标签和一个按钮,用于触发网络请求。

当用户点击按钮时,我们首先显示一个ProgressDialog,然后创建一个RequestThread,并在其中执行网络请求。一旦请求完成,RequestThread将发出一个finished信号,我们在MainWindow中连接这个信号,以便在请求完成时执行onRequestFinished方法。在这个方法中,我们隐藏ProgressDialog并更新标签以反映请求的结果。

注意,这只是一个简单的示例,用于说明如何在PyQt5中执行网络请求并显示一个执行中的对话框。在实际应用中,您可能需要对代码进行一些修改,以满足您的特定需求。

二、继承QMainWindow

如果您的MainWindow继承自QMainWindow,您需要对代码进行一些修改才能使ProgressDialog正确显示。因为QMainWindow已经有一个菜单栏、工具栏、状态栏等,所以ProgressDialog需要以对话框的形式显示。

import sys
import requests
from PyQt5.QtWidgets import QApplication, QMainWindow, QDialog, QLabel, QVBoxLayout, QAction, QMessageBox
from PyQt5.QtCore import Qt, QThread, pyqtSignal


class RequestThread(QThread):
    finished = pyqtSignal(bool)

    def __init__(self, url):
        super().__init__()
        self.url = url

    def run(self):
        try:
            response = requests.get(self.url)
            if response.status_code == 200:
                self.finished.emit(True)
            else:
                self.finished.emit(False)
        except:
            self.finished.emit(False)


class ProgressDialog(QDialog):
    def __init__(self, parent=None):
        super().__init__(parent, Qt.CustomizeWindowHint | Qt.WindowTitleHint)
        self.setWindowTitle("执行中")
        self.setFixedSize(200, 100)
        layout = QVBoxLayout(self)
        self.label = QLabel("正在执行,请稍候...", self)
        layout.addWidget(self.label, alignment=Qt.AlignCenter)

    def setMessage(self, text):
        self.label.setText(text)


class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("网络请求")
        self.setFixedSize(300, 100)
        centralWidget = QWidget(self)
        layout = QVBoxLayout(centralWidget)
        self.label = QLabel("点击按钮执行网络请求", centralWidget)
        layout.addWidget(self.label, alignment=Qt.AlignCenter)
        self.button = QAction("执行请求", self)
        self.button.triggered.connect(self.executeRequest)
        self.addAction(self.button)
        self.progressDialog = ProgressDialog(self)

    def executeRequest(self):
        url = "https://www.example.com"
        self.progressDialog.show()
        self.progressDialog.setMessage("正在执行网络请求,请稍候...")
        self.requestThread = RequestThread(url)
        self.requestThread.finished.connect(self.onRequestFinished)
        self.requestThread.start()

    def onRequestFinished(self, success):
        self.progressDialog.hide()
        if success:
            self.label.setText("网络请求执行成功")
        else:
            self.label.setText("网络请求执行失败")
            QMessageBox.warning(self, "警告", "网络请求执行失败!")


if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec_())

在这个例子中,我们将ProgressDialog的父窗口设置为MainWindow,并设置了Qt.CustomizeWindowHint | Qt.WindowTitleHint标志,以使其作为对话框显示。我们还使用了QWidget作为MainWindow的中央窗口部件,以便正确放置标签和按钮。

我们还将按钮修改为QAction,并通过addAction将其添加到MainWindow的菜单栏中。当用户点击按钮时,我们将ProgressDialog显示出来,并使用QAction的triggered信号触发executeRequest方法。

在onRequestFinished方法中,我们隐藏ProgressDialog并根据请求结果更新标签。如果请求失败,我们还使用QMessageBox显示一个警告框。

三、模态对话框

如果您希望ProgressDialog显示时,MainWindow中的其他部分不能被操作,但MainWindow本身仍然可以被关闭和最小化,可以使用setWindowModality方法将ProgressDialog设置为ApplicationModal模态对话框。

以下是示例代码,将ProgressDialog设置为ApplicationModal模态对话框:

import sys
import requests
from PyQt5.QtWidgets import QApplication, QMainWindow, QDialog, QLabel, QVBoxLayout, QAction, QMessageBox


class RequestThread(QThread):
    finished = pyqtSignal(bool)

    def __init__(self, url):
        super().__init__()
        self.url = url

    def run(self):
        try:
            response = requests.get(self.url)
            if response.status_code == 200:
                self.finished.emit(True)
            else:
                self.finished.emit(False)
        except:
            self.finished.emit(False)


class ProgressDialog(QDialog):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setWindowTitle("执行中")
        self.setFixedSize(200, 100)
        layout = QVBoxLayout(self)
        self.label = QLabel("正在执行,请稍候...", self)
        layout.addWidget(self.label, alignment=Qt.AlignCenter)

    def setMessage(self, text):
        self.label.setText(text)


class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("网络请求")
        self.setFixedSize(300, 100)
        centralWidget = QWidget(self)
        layout = QVBoxLayout(centralWidget)
        self.label = QLabel("点击按钮执行网络请求", centralWidget)
        layout.addWidget(self.label, alignment=Qt.AlignCenter)
        self.button = QAction("执行请求", self)
        self.button.triggered.connect(self.executeRequest)
        self.addAction(self.button)
        self.progressDialog = ProgressDialog(self)
        self.progressDialog.setWindowModality(Qt.ApplicationModal)

    def executeRequest(self):
        url = "https://www.example.com"
        self.progressDialog.show()
        self.progressDialog.setMessage("正在执行网络请求,请稍候...")
        self.requestThread = RequestThread(url)
        self.requestThread.finished.connect(self.onRequestFinished)
        self.requestThread.start()

    def onRequestFinished(self, success):
        self.progressDialog.hide()
        if success:
            self.label.setText("网络请求执行成功")
        else:
            self.label.setText("网络请求执行失败")
            QMessageBox.warning(self, "警告", "网络请求执行失败!")


if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec_())

使用 setWindowModality 方法将 ProgressDialog 设置为 ApplicationModal 模态对话框会阻止用户与 MainWindow 进行交互,包括关闭和最小化窗口。在这种情况下,您需要为 ProgressDialog 添加一个关闭按钮或使用其他方法来关闭 ProgressDialog。

如果您希望ProgressDialog显示时,MainWindow中的其他部分不能被操作,但MainWindow本身仍然可以被关闭和最小化,可以尝试使用 setEnabled 方法禁用 MainWindow 中的其他部件。

四、禁用其他部件

以下是示例代码,使用 setEnabled 方法禁用 MainWindow 中的其他部件:

import sys
import requests
from PyQt5.QtCore import Qt, QThread, pyqtSignal
from PyQt5.QtWidgets import QApplication, QMainWindow, QDialog, QLabel, QVBoxLayout, QAction, QMessageBox


class RequestThread(QThread):
    finished = pyqtSignal(bool)

    def __init__(self, url):
        super().__init__()
        self.url = url

    def run(self):
        try:
            response = requests.get(self.url)
            if response.status_code == 200:
                self.finished.emit(True)
            else:
                self.finished.emit(False)
        except:
            self.finished.emit(False)


class ProgressDialog(QDialog):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setWindowTitle("执行中")
        self.setFixedSize(200, 100)
        layout = QVBoxLayout(self)
        self.label = QLabel("正在执行,请稍候...", self)
        layout.addWidget(self.label, alignment=Qt.AlignCenter)

    def setMessage(self, text):
        self.label.setText(text)


class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("网络请求")
        self.setFixedSize(300, 100)
        centralWidget = QWidget(self)
        layout = QVBoxLayout(centralWidget)
        self.label = QLabel("点击按钮执行网络请求", centralWidget)
        layout.addWidget(self.label, alignment=Qt.AlignCenter)
        self.button = QAction("执行请求", self)
        self.button.triggered.connect(self.executeRequest)
        self.addAction(self.button)
        self.progressDialog = ProgressDialog(self)

    def executeRequest(self):
        url = "https://www.example.com"
        self.progressDialog.show()
        self.progressDialog.setMessage("正在执行网络请求,请稍候...")
        self.setEnabled(False)  # 禁用 MainWindow 中的其他部件
        self.requestThread = RequestThread(url)
        self.requestThread.finished.connect(self.onRequestFinished)
        self.requestThread.start()

    def onRequestFinished(self, success):
        self.progressDialog.hide()
        self.setEnabled(True)  # 启用 MainWindow 中的其他部件
        if success:
            self.label.setText("网络请求执行成功")
        else:
            self.label.setText("网络请求执行失败")
            QMessageBox.warning(self, "警告", "网络请求执行失败!")


if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec_())

在这个例子中,我们使用 setEnabled 方法禁用 MainWindow 中的其他部件。这意味着 ProgressDialog 显示时,用户无法与 MainWindow 中的其他部件进行交互。在网络请求完成后,我们使用 setEnabled 方法启用 MainWindow 中的其他部件。这样,用户就可以在 ProgressDialog 显示时关闭或最小化 MainWindow。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AI克斯

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值