为什么在使用 QWebView 时必须调用 QApplication.processEvents() 直到 QNetworkRequest 完成? [英] Why must QApplication.processEvents() be called until QNetworkRequest is finished when using QWebView?

查看:51
本文介绍了为什么在使用 QWebView 时必须调用 QApplication.processEvents() 直到 QNetworkRequest 完成?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

通常,当我通过 Qt 4.8 执行网络请求时,我不需要显式运行 QApplication.processEvents() (请参阅此 StackOverflow 代码示例).

Normally, when I perform a network request via Qt 4.8 I don't need to explicitly run QApplication.processEvents() (see this StackOverflow code example).

但是,当我在 QWebView 中从 JavaScript 发出网络请求时,除非我在请求完成之前调用该方法,否则这将不起作用,如下所示(此处为语法高亮要点).

However when I issue the network request from JavaScript in a QWebView, this will not work unless I call that method until the request is finished, as seen below (syntax-highlighted gist here).

澄清:
当我省略 processEvents() 调用时,请求甚至没有发送,尽管 finished 插槽似乎附加了我的理解.>

CLARIFICATION:
The request is not even sent when I omit the processEvents() call although the finished slots seem to be attached as I understand it.

from PyQt4 import QtCore, QtGui, QtNetwork, QtWebKit

class MainWindow(QtGui.QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()

        QtNetwork.QNetworkProxyFactory.setUseSystemConfiguration(True)
        self.view = QtWebKit.QWebView(self)
        self.setCentralWidget(self.view)
        self.view.setPage(QtWebKit.QWebPage(self.view))

        self.view.page().mainFrame().javaScriptWindowObjectCleared.connect(self.refreshJS)

        self.view.setHtml(
            '''<html>
            <body>
                    LOADING...
                    <script>
                    <!--
                            APP.request();
                    //-->
                    </script>
            </body>
            </html>'''
        )

    @QtCore.pyqtSlot()
    def request(self):
        request = QtNetwork.QNetworkRequest(QtCore.QUrl('http://localhost/test.php'))

        manager = QtNetwork.QNetworkAccessManager()
        manager.finished.connect(self.managerFinished)

        reply = manager.post(request, b'a=A')
        reply.finished.connect(self.finished)

        ############################################################
        ### FIXME: Request never even *sent* if this is missing  ###
        ############################################################

        while not reply.isFinished():
          QtGui.QApplication.processEvents()

        ##########################################################

        print('request FINISHED? '+str(reply.isFinished())+', ERROR '+str(reply.error()))

    def finished(self):
        print('finished')

    def managerFinished(self):
        print('managerFinished')

    def refreshJS(self):
        print('refreshJS')
        self.view.page().mainFrame().addToJavaScriptWindowObject('APP', self)

if __name__ == '__main__':
    import os, sys
    app = QtGui.QApplication(sys.argv)
    MainWindow().show()
    sys.exit(app.exec_())

推荐答案

您对 QNetworkAccessManager 的使用与链接中指出的使用有很大的不同.请注意,您的版本是同步的:您通过等待回复来阻止请求"槽中的事件循环,因此除非您手动推送事件,否则 QNetworkAccessManager 无法工作.另一方面,指向的示例是异步的:它创建请求,连接完成"信号并让事件循环工作.这样事件循环不会被阻塞,网络管理器运行良好.我了解在您的情况下,请求"插槽需要同步,因此此处必须使用 processEvents.

There is one big difference between your usage of QNetworkAccessManager and one pointed in the link. Notice that your version is synchronous: you block the event loop in 'request' slot by waiting for reply, thus QNetworkAccessManager cannot work unless you push the events by hand. From the other side the pointed example is asynchronous: it creates request, connects 'finished' signal and lets event loop to work. This way event loop is not blocked and network manager works well. I understand that in your situation 'request' slot needs to be synchronous, thus processEvents is a must here.

编辑

如果你想让 request 异步,那么你需要确保 QNetworkAccessManager 对象在 request 方法之外是持久的.在 __init__(self) 中初始化它,并在 请求中使用它来 POST.可能QNetworkReply`也需要持久化,你需要检查一下.

If you want to make the request asynchronous, then you need to be sure that QNetworkAccessManager object is persistent outside the request method. Initialize it in __init__(self) and use it to POST in the request. ProbablyQNetworkReply` needs to be persistent too, you need to check it.

这篇关于为什么在使用 QWebView 时必须调用 QApplication.processEvents() 直到 QNetworkRequest 完成?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆