2

私はPython 2.7PySideを使用しています。大きな html ファイルを pdf ファイルにエクスポートする必要があります。

でロードしてから、 pdf形式用に構成されQWebViewた形式で印刷しようとしました。QPrinterこれはうまくいきます。

ただし、私のソリューションには大きな問題が 1 つあります。 を呼び出す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_()
4

1 に答える 1

2

この問題を解決するには、スレッドを使用する必要があると思います。メインスレッドで実行されているように見えるQWebView.print_()ため、GUI の実行がブロックされます。

threadingPython のモジュールまたは Qt のモジュールを使用する 2 つのオプションがありますQThread

この質問は、s の使用方法を示していますQThread。基本的:

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 スレッドにアクセスできないことを示すだけかもしれません (確かではありません)。

于 2013-01-02T11:21:39.933 に答える