【问题标题】:Is there any way to call synchronously the method 'toHtml' which is QWebEnginePage's object?有什么方法可以同步调用 QWebEnginePage 的对象“toHtml”方法?
【发布时间】:2018-04-14 11:46:03
【问题描述】:

我正在尝试从 QWebEnginePage 对象获取 html 代码。根据 Qt 参考,QWebEnginePage 对象的 'toHtml' 是异步方法,如下所示。

异步方法将页面内容检索为 HTML,包含在 HTML 和 BODY 标记中。成功完成后,使用页面内容调用 resultCallback。

所以我试图找出如何同步调用这个方法。

我想要得到的结果如下。

class MainWindow(QWidget):
  html = None
  ...
  ...
  def store_html(self, data):
    self.html = data

  def get_html(self):
    current_page = self.web_view.page()
    current_page.toHtml(self.store_html)
    # I want to wait until the 'store_html' method is finished
    # but the 'toHtml' is called asynchronously, return None when try to return self.html value like below.
    return self.html 
  ...
  ...

感谢您阅读本文。

祝大家有个美好的一天。

【问题讨论】:

  • 不清楚你为什么想要这个。 QWebEngine 基于 Blink,它为 Web 内容运行一个单独的进程(就像大多数现代浏览器一样。)由于进程之间的 IPC 调用可能需要时间,QWebEngine 要求您定义一个回调函数,以便您的主进程的事件循环可以继续IPC 调用完成时。因此,在不知道这个问题的理由的情况下,提供最佳答案将是在黑暗中刺伤。
  • @MrEricSir 我不知道 QWebEngine 基于 Blink 框架。我只是想在使用我创建的一些按钮传递 html 响应后转换 web 视图屏幕的内容。谢谢你的回答。

标签: python pyqt pyqt5 qwebengineview qwebenginepage


【解决方案1】:

获得该行为的一种简单方法是使用QEventLoop()。这个类的一个对象阻止了exec_()之后的代码被执行,这并不意味着GUI不能继续工作。

from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
from PyQt5.QtWebEngineWidgets import *


class Widget(QWidget):
    toHtmlFinished = pyqtSignal()

    def __init__(self, *args, **kwargs):
        QWidget.__init__(self, *args, **kwargs)
        self.setLayout(QVBoxLayout())
        self.web_view = QWebEngineView(self)
        self.web_view.load(QUrl("http://doc.qt.io/qt-5/qeventloop.html"))
        btn = QPushButton("Get HTML", self)
        self.layout().addWidget(self.web_view)
        self.layout().addWidget(btn)
        btn.clicked.connect(self.get_html)
        self.html = ""

    def store_html(self, html):
        self.html = html
        self.toHtmlFinished.emit()

    def get_html(self):
        current_page = self.web_view.page()
        current_page.toHtml(self.store_html)
        loop = QEventLoop()
        self.toHtmlFinished.connect(loop.quit)
        loop.exec_()
        print(self.html)


if __name__ == '__main__':
    import sys
    app = QApplication(sys.argv)
    w = Widget()
    w.show()
    sys.exit(app.exec_())

注意:同样的方法适用于 PySide2。

【讨论】:

  • 非常感谢。你的回答对我很有帮助。祝你有美好的一天!
【解决方案2】:

您可以使用作为 multiprocessing.Pipe 的 send 方法一侧创建的 multiprocessing.Connection 对象作为回调,然后立即使用管道的 recv 方法的另一端。在收到 html 之前,Recv 会一直阻塞,所以请记住这一点

示例:

from multiprocessing import Pipe

class MainWindow(QWidget):
    def __init__(...):
        ...
        self.from_loopback,self.to_loopback=Pipe(False)

    def get_html(self):
        current_page = self.web_view.page()
        current_page.toHtml(self.to_loopback.send)
        return self.from_loopback.recv() 

【讨论】:

猜你喜欢
  • 2011-10-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-27
  • 2012-09-06
  • 1970-01-01
相关资源
最近更新 更多