【问题标题】:gui locked when calling QWebView.print_()gui 在调用 QWebView.print_() 时被锁定
【发布时间】:2012-12-16 15:36:15
【问题描述】:

我正在使用 Python 2.7PySide,我需要将一个大的 html 文件导出到一个 pdf 文件。

我尝试使用QWebView 加载它,然后将其打印到为pdf 格式配置的QPrinter。这工作正常。

但是,我的解决方案存在一个大问题:当我调用 QWebView.print_() 时,gui 被锁定,对于 windows,我的程序看起来像是崩溃了。发生这种情况是因为我的 html 很大(1000 页或更多)。

所以我的问题是:有没有一种干净的方法可以避免这种“崩溃”?

编辑:

我尝试在单独的线程中进行打印,就像 jadkik94 建议的那样。 据我了解,下面的代码应该可以工作。不幸的是,它随机崩溃。 ;) 任何想法为什么会这样?

import sys
from PySide import QtGui, QtWebKit, QtCore

class PrintThread(QtCore.QThread):
    def __init__(self, webview, printer, parent=None):
        super(PrintThread, self).__init__(parent)
        self._webview = webview
        self._printer = printer

    def run(self):
        self._webview.print_(self._printer)

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

        # a printer to print on
        self._myPrinter = QtGui.QPrinter()
        self._myPrinter.setOutputFormat(QtGui.QPrinter.PdfFormat)
        self._myPrinter.setPrintRange(QtGui.QPrinter.AllPages)
        self._myPrinter.setOrientation(QtGui.QPrinter.Portrait)
        self._myPrinter.setPaperSize(QtGui.QPrinter.A4)
        self._myPrinter.setNumCopies(1)

        # a webview for loading the html and printing it
        self._webview = QtWebKit.QWebView(self)
        self.setCentralWidget( self._webview )
        self._webview.loadFinished.connect(self.webViewLoadFinished)

        # print-preview-dialog
        self._previewDlg = QtGui.QPrintPreviewDialog(self._myPrinter)
        #self._previewDlg.paintRequested.connect(self.dlgPaintRequestNoThread) # works but freezes the mainthread
        self._previewDlg.paintRequested.connect(self.dlgPaintRequestWithThread) # as far is i understand this should work... but crashes randomly ;)

        # load the html
        self._webview.load('index.htm') # file is 2MB

    def webViewLoadFinished(self):
        # when webview has finished loading, show the dialog
        self._previewDlg.show()

    def dlgPaintRequestNoThread(self):
        self._webview.print_(self._myPrinter)

    def dlgPaintRequestWithThread(self):
        self.printPages()

        # wait for the print-thread to finish without blocking the mainthread
        eventLoop =  QtCore.QEventLoop()
        self.worker.finished.connect(eventLoop.quit)
        eventLoop.exec_()

    def printPages(self):
        self.worker = PrintThread(self._webview, self._myPrinter)
        self.worker.finished.connect(self.donePrinting)

        self.progressDlg = QtGui.QProgressDialog()
        self.progressDlg.setCancelButton(None)
        self.progressDlg.show()

        self.worker.start()

    def donePrinting(self):
        self.progressDlg.close()

if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)
    window = MyWindow()
    window.show()
    app.exec_()

【问题讨论】:

    标签: python qt pdf-generation pyside qwebview


    【解决方案1】:

    我相信你需要使用线程来解决这个问题。 QWebView.print_() 似乎在主线程中运行,因此会阻止您的 GUI 运行。

    您有 2 个选项,您可以使用 Python 的 threading 模块或 Qt 的 QThreads。

    This question 展示了如何使用QThreads。基本上:

    class PrintThread(QtCore.QThread):
        def __init__(self, webview, parent=None):
            super(PrintThread, self).__init__(parent)
            self.webview = webview
    
        def run(self):
            # Get a printer from somewhere
            self.webview.print_(printer)
    

    然后:

    def printPage(self):
        worker = PrintThread(self.page)
        worker.finished.connect(self.donePrinting)
        # Show a loading dialog
        worker.start()
    
    def donePrinting(self):
        # Close the loading dialog
        pass
    

    你可以对 threading 模块应用同样的东西,但是既然你已经在使用 pyside,为什么不也使用它呢。另外,我不确定其他线程(QThread 除外)是否会干扰 Qt GUI,它可能只是告诉您无法从另一个线程访问 GUI 线程(但不确定)。

    【讨论】:

    • 感谢您的帮助。到目前为止这看起来不错,但是我如何将它与 QPrintPreviewWidget 结合起来?如果我将 previewWidget 的 paintRequested 信号连接到一个插槽,我在该插槽中启动 QThread 进行打印,则预览不会更新。如果我不在插槽中启动线程,它会起作用,但随后会再次阻止我的 gui。关于如何将 previewWidget 与打印线程一起使用的任何想法?
    • 我无法以这种方式帮助您...请将其作为另一个问题发布或编辑您的帖子以包含一些代码。我认为虽然它不应该有很大的不同......
    猜你喜欢
    • 2015-09-02
    • 1970-01-01
    • 1970-01-01
    • 2013-09-13
    • 2018-01-06
    • 1970-01-01
    • 2021-09-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多