Проблема зацикливания PyQt5, работает только последняя итерация объекта QWebEngineView - PullRequest
0 голосов
/ 13 ноября 2018

У меня нет опыта работы с Qt / PyQt. Я просто пытаюсь использовать PyQt для возможностей веб-движка, чтобы «преобразовать» папку HTML-файлов в PDF-документы.

Код работает хорошо, если имеется только 1 html-файл, но при наличии нескольких html-файлов он генерирует pdf только для последнего файла в цикле .

Я думаю, что проблема должна быть связана с вещами Qt, циклами, событиями и т. Д., Но я понятия не имею, с чего начать. Как вы можете сказать, я использую только Qt для создания html-> pdf, я не заинтересован в создании GUI.

Я читал об использовании QApplication.processEvents() в конце цикла, это может исправить, но результат был тот же. Я попытался добавить в код режим сна / паузы, тоже самое.

import sys
import os

from PyQt5.QtWidgets import QApplication
from PyQt5.QtWebEngineWidgets import QWebEngineView
from PyQt5.QtCore import QDir, QUrl

# read somewhere this is needed to load local html, works without for me though
sys.argv.append("--disable-web-security")
app = QApplication(sys.argv)

iter_num = 0

directory = 'my_webfile_directory'
for filename in os.listdir(directory):
    if filename.endswith(".htm") or filename.endswith(".html"):
        with open(os.path.join(directory, filename), 'r') as myfile:

            print(filename)
            raw_html = myfile.read()
            # init qt web view
            view = QWebEngineView()
            view.setHtml(raw_html)

            # set to close web view after pdf is created
            view.page().pdfPrintingFinished.connect(view.close)
            # generate filename
            iter_num += 1
            outputfilename = str(iter_num) + ".pdf"
            outputfullpath = os.path.join(directory, outputfilename)

            def save_pdf(finished):
                view.page().printToPdf(outputfullpath)
            # when web view is ready, save the pdf
            view.loadFinished.connect(save_pdf)
            # QApplication.processEvents()

app.exec()

1 Ответ

0 голосов
/ 13 ноября 2018

Я думаю, QWebEngineView не является поточно-ориентированным, потому что я смог обеспечить его последовательную работу, создав очередь файлов для обработки и выполняя один за другим, используя сигнал, вот демонстрационное приложение:

import sys
import os

from PyQt5.QtWidgets import QApplication, QMainWindow, QMessageBox
from PyQt5.QtWebEngineWidgets import QWebEngineView
from PyQt5.QtCore import QObject, QDir, QUrl, pyqtSignal


class HtmlToPdfConverter(QObject):

    queueProcessed = pyqtSignal()

    def __init__(self):
        super().__init__()

        self._queue = []
        self._current = None

    def queue(self, html_file, output_file):
        self._queue.append((html_file, output_file))

    def process_queue(self):
        if self._queue:
            raw_html = ''
            self._current = self._queue.pop(0)
            with open(self._current[0], 'r') as my_file:
                raw_html = my_file.read()

            view = QWebEngineView()
            view.loadFinished.connect(self._get_load_finished_event(view))
            view.page().pdfPrintingFinished.connect(self._get_printing_finished_event(view))
            view.setHtml(raw_html)
        else:
            self.queueProcessed.emit()

    def _get_load_finished_event(self, view):
        def _load_finished(success):
            if success:
                view.page().printToPdf(self._current[1])
        return _load_finished

    def _get_printing_finished_event(self, view):
        def _printing_finished(file, success):
            view.close()
            self.process_queue()
        return _printing_finished


class App(QApplication):
    def __init__(self, sys_argv):
        super().__init__(sys_argv)

        self.dummy_window = QMainWindow()
        self.dummy_window.show()

    def generate_pdfs(self, directory):
        converter = HtmlToPdfConverter()
        converter.queueProcessed.connect(self._queue_processed)

        iter_num = 0

        for filename in os.listdir(directory):
            if filename.endswith(".htm") or filename.endswith(".html"):
                iter_num += 1
                out_filename = os.path.join(directory, str(iter_num) + ".pdf")
                converter.queue(os.path.join(directory, filename), out_filename)

        converter.process_queue()

    def _queue_processed(self):
        QMessageBox.information(self.dummy_window, 'Pdf Generator', 'All PDF files have been generated.')


if __name__ == '__main__':
    app = App(sys.argv)
    app.generate_pdfs('c:/temp/test')

    sys.exit(app.exec_())
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...