I'm trying to get some simple html to be saved onto a pdf document using PyQt5.
The webpage renders properly, using the show() command I can get a window showing me the web content in question, however trying to print it to pdf only results in blank pdfs.
This is on python 3.6 and as of posting this question I have the current PyQt5 version. (Windows 10, 64 Bit)
There's a lot of older questions to this already on stackoverflow, but I found most of them use functions that no longer exist.
The problematic code follows:
from PyQt5.QtWebEngineWidgets import QWebEngineView, QWebEngineSettings
from PyQt5 import QtWidgets
from PyQt5.QtPrintSupport import QPrinter
from PyQt5 import QtCore
[...]
app = QtWidgets.QApplication(sys.argv)
QWebEngineSettings.globalSettings().setAttribute(QWebEngineSettings.PluginsEnabled, True)
QWebEngineSettings.globalSettings().setAttribute(QWebEngineSettings.ScreenCaptureEnabled, True)
loader = QWebEngineView()
#loader.setAttribute(QtCore.Qt.WA_DontShowOnScreen, True)
loader.setAttribute(QtCore.Qt.WA_DeleteOnClose, True)
loader.setZoomFactor(1)
loader.setHtml(webpage)
printer = QPrinter()
printer.setPageSize(QPrinter.A4)
printer.setOutputFormat(QPrinter.PdfFormat)
printer.setOutputFileName("test.pdf")
printer.setOrientation(QPrinter.Portrait)
printer.setFullPage(True)
def emit_pdf(finished):
loader.show()
loader.render(printer)
if self.open_on_complete:
import webbrowser
webbrowser.open("test.pdf")
#app.exit()
loader.loadFinished.connect(emit_pdf)
app.exec()
There is no need to use use QPrinter in Qt5, because QWebEnginePage has a dedicated printToPdf method:
import sys
from PyQt5 import QtCore, QtWidgets, QtWebEngineWidgets
app = QtWidgets.QApplication(sys.argv)
loader = QtWebEngineWidgets.QWebEngineView()
loader.setZoomFactor(1)
loader.page().pdfPrintingFinished.connect(
lambda *args: print('finished:', args))
loader.load(QtCore.QUrl('https://en.wikipedia.org/wiki/Main_Page'))
def emit_pdf(finished):
loader.show()
loader.page().printToPdf("test.pdf")
loader.loadFinished.connect(emit_pdf)
app.exec()
There's also a print method that will render to a printer, if you really want that.
Related
I was learning Qt6, and I wrote a demo putting a local html file into it to test the QWebEngineView Widget. However, the web page shows the info:
Your file counldn't be accessed
It may have been moved, edited, or deleted.
ERR_FILE_NOT_FOUND
Here is my test.py source code:
import sys
from PySide6.QtWidgets import (QApplication, QWidget, QVBoxLayout)
from PySide6 import QtCore
from PySide6.QtWebEngineWidgets import QWebEngineView
class webView(QWidget):
def __init__(self):
super(webView, self).__init__()
self.layout = QVBoxLayout(self)
self.webV = QWebEngineView()
self.fileDir = QtCore.QFileInfo("./docs.html").absoluteFilePath()
print(self.fileDir)
self.webV.load(QtCore.QUrl("file:///" + self.fileDir))
self.layout.addWidget(self.webV)
if __name__ == "__main__":
app = QApplication([])
web = webView()
web.show()
sys.exit(app.exec())
In Addition, the docs.html has been put into the same directory as the test.py file. And when I print the web.fileDir, the result is correct.
You are hardcoded the url and the path may be wrong, in these cases the url is better step by step. I assume that the html is next to the .py then the solution is:
import os
from pathlib import Path
import sys
from PySide6.QtCore import QUrl
from PySide6.QtWidgets import QApplication, QVBoxLayout, QWidget
from PySide6.QtWebEngineWidgets import QWebEngineView
CURRENT_DIRECTORY = Path(__file__).resolve().parent
class webView(QWidget):
def __init__(self):
super(webView, self).__init__()
filename = os.fspath(CURRENT_DIRECTORY / "docs.html")
url = QUrl.fromLocalFile(filename)
self.webV = QWebEngineView()
self.webV.load(url)
layout = QVBoxLayout(self)
layout.addWidget(self.webV)
if __name__ == "__main__":
app = QApplication([])
web = webView()
web.show()
sys.exit(app.exec())
In Qt in general is strongly preferred to use the qrc files, and the Qt resource management system. Here: Can QWebView load images from Qt resource files? is a small yet, neat example of something that is similar to your problem. You may also view the official PySide6 resource usage :
https://doc.qt.io/qtforpython/tutorials/basictutorial/qrcfiles.html
I would like to know how to enable Adobe Reader in QWebEngineView with PyQt5.
I've already created this piece of code without any success :
import sys
from PyQt5 import QtCore, QtWidgets, QtWebEngineWidgets
app = QtWidgets.QApplication(sys.argv)
web = QtWebEngineWidgets.QWebEngineView()
web.settings().setAttribute(QtWebEngineWidgets.QWebEngineSettings.PluginsEnabled, True)
web.load(QtCore.QUrl('file:///path/to/my/file.pdf'))
web.show()
sys.exit(app.exec_())
Thanks in advance!
When I browse to a page using the following code, the result is in another language (Russian I think). When I browse to the same url in other browsers I get the English 404 page as expected. I tried setting the accept language, but that didn't help. What am I missing?
import sys
from PyQt5 import QtWidgets, QtCore
from PyQt5.QtWebEngineWidgets import QWebEngineView
app = QtWidgets.QApplication(sys.argv)
w = QWebEngineView()
w.page().profile().setHttpAcceptLanguage('en') # This doesn't help
w.load(QtCore.QUrl('http://turbobit.net/download')) # Goes to russian? 404 page
w.show()
app.exec_()
The following webkit version works as expected
import sys
from PyQt5 import QtWidgets, QtCore
from PyQt5.QtWebKitWidgets import QWebView
app = QtWidgets.QApplication(sys.argv)
w = QWebView()
w.setUrl(QtCore.QUrl('http://turbobit.net/download')) # Loads correct English 404 page
w.show()
app.exec_()
You need to set the language before creating the view:
import sys
from PyQt5 import QtWidgets, QtCore
from PyQt5.QtWebEngineWidgets import QWebEngineView, QWebEngineProfile
app = QtWidgets.QApplication(sys.argv)
QWebEngineProfile.defaultProfile().setHttpAcceptLanguage('en')
w = QWebEngineView()
w.load(QtCore.QUrl('http://turbobit.net/download'))
w.show()
app.exec_()
I have tried adding the pdf.js viewer files in my project and it works in browsers like Chrome, Mozilla, Safari, etc, but it's not loading some pages in node-webkit and PyQt webkit.
I am trying to load the file using an iframe, like this:
<iframe src="/test/?file=/assets/pdf/example.pdf#page=3"> </iframe>
Below are some more up-to-date demo scripts for using pdf.js with PyQt4/QtWebKit or PyQt5/QtWebEngine. To try these, first download the latest stable version of pdf.js and unpack the zip file into a suitable location. (NB: if you're on Linux your distro may already have a pdf.js package, so that could be installed instead).
UPDATE:
As of Qt-5.13.0, it is also possible to use the built-in Chromium PDF Viewer with QWebEngineView:
import sys
from PyQt5 import QtCore, QtWidgets, QtWebEngineWidgets
PDF = 'file://path/to/my/sample.pdf'
class Window(QtWebEngineWidgets.QWebEngineView):
def __init__(self):
super().__init__()
self.settings().setAttribute(
QtWebEngineWidgets.QWebEngineSettings.PluginsEnabled, True)
self.settings().setAttribute(
QtWebEngineWidgets.QWebEngineSettings.PdfViewerEnabled, True)
self.load(QtCore.QUrl.fromUserInput(PDF))
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
window = Window()
window.setGeometry(600, 50, 800, 600)
window.show()
sys.exit(app.exec_())
PyQt5/QtWebEngine pdfjs script:
UPDATE:
NB: as of Aug 2022, it may be necessary to use the legacy build of pdfjs (i.e. the build for "older browsers" on the download page) to keep things working with PyQt5. The stable build should work okay with PyQt6, though.
import sys
from PyQt5 import QtCore, QtWidgets, QtWebEngineWidgets
PDFJS = 'file:///path/to/pdfjs-1.9.426-dist/web/viewer.html'
# PDFJS = 'file:///usr/share/pdf.js/web/viewer.html'
PDF = 'file:///path/to/my/sample.pdf'
class Window(QtWebEngineWidgets.QWebEngineView):
def __init__(self):
super().__init__()
self.load(QtCore.QUrl.fromUserInput('%s?file=%s' % (PDFJS, PDF)))
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
window = Window()
window.setGeometry(600, 50, 800, 600)
window.show()
sys.exit(app.exec_())
PyQt4/QtWebKit pdfjs script:
import sys
from PyQt4 import QtCore, QtGui, QtWebKit
PDFJS = 'file:///path/to/pdfjs-1.9.426-dist/web/viewer.html'
# PDFJS = 'file:///usr/share/pdf.js/web/viewer.html'
PDF = 'file:///path/to/my/sample.pdf'
class Window(QtWebKit.QWebView):
def __init__(self):
super().__init__()
self.load(QtCore.QUrl.fromUserInput('%s?file=%s' % (PDFJS, PDF)))
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
window = Window()
window.setGeometry(600, 50, 800, 600)
window.show()
sys.exit(app.exec_())
I've found this thread over at the Qt Forums, where thebeast44 posted a snippet of Qt code answering your question. My translation to python is below.
You'll also need to unpack the res folder from the author's original code, I think he just modified the viewer... I've also attached said code here.
from PyQt4 import QtCore
from PyQt4 import QtGui
from PyQt4 import QtNetwork
from PyQt4 import QtWebKit
class PDFViewer(QtWebKit.QWebView):
pdf_viewer_page = 'res/pdf-viewer.html'
def __init__(self, parent=None):
super().__init__(parent)
self.settings = QtWebKit.QWebSettings.globalSettings()
self.settings.setAttribute(QtWebKit.QWebSettings.LocalContentCanAccessFileUrls, True )
self.settings.setAttribute(QtWebKit.QWebSettings.LocalContentCanAccessRemoteUrls, True )
self.settings.setAttribute(QtWebKit.QWebSettings.DeveloperExtrasEnabled, True )
nam = QtNetwork.QNetworkAccessManager()
page = QtWebKit.QWebPage(self)
page.setNetworkAccessManager(nam)
self.setPage(page)
self.loadFinished.connect(self.onLoadFinish)
self.setUrl(QtCore.QUrl(self.pdf_viewer_page))
def onLoadFinish(self, success):
if success:
self.page().mainFrame().evaluateJavaScript("init();")
if __name__ == '__main__':
import sys
app = QtGui.QApplication(sys.argv)
viewer = PDFViewer(parent=None)
viewer.show()
sys.exit(app.exec_())
From PyQt5 v5.13 you can load PDF files with the chromium API. According to the documentation https://doc.qt.io/qt-5/qtwebengine-features.html#pdf-file-viewing this option is by default enabled.
This minimal example is adapted from Simple Browser
import sys
from pathlib import Path
from PyQt5 import QAxContainer
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QWidget, QVBoxLayout, QPushButton, QLineEdit, QApplication
class Main(QWidget):
def __init__(self, parent=None):
super(Main, self).__init__(parent)
self.main_layout = QVBoxLayout(self)
self.qlineedit = QLineEdit()
self.qlineedit.returnPressed.connect(self.go_action)
self.main_layout.addWidget(self.qlineedit)
self.read_btn = QPushButton('Test')
self.read_btn.clicked.connect(self.go_action)
self.main_layout.addWidget(self.read_btn)
self.WebBrowser = QAxContainer.QAxWidget(self)
self.WebBrowser.setFocusPolicy(Qt.StrongFocus)
self.WebBrowser.setControl("{8856F961-340A-11D0-A96B-00C04FD705A2}")
self.main_layout.addWidget(self.WebBrowser)
def go_action(self):
# convert system path to web path
f = Path(self.qlineedit.text()).as_uri()
# load object
self.WebBrowser.dynamicCall('Navigate(const QString&)', f)
if __name__ == "__main__":
a = QApplication(sys.argv)
w = Main()
w.show()
sys.exit(a.exec_())
This example:
I'd like PyQt to load an image and display it from the web. Dozens of examples I've found online did not work, as they are for downloading the image.
I simply want to view it.
Something like
from PyQt4.QtWebKit import *
web = QWebView()
web.load(QUrl("http://stackoverflow.com/content/img/so/logo.png"))
import sys
from PyQt4 import QtCore, QtGui, QtWebKit
app = QtGui.QApplication(sys.argv)
web = QtWebKit.QWebView()
web.load(QtCore.QUrl("http://upload.wikimedia.org/wikipedia/commons/a/af/Tux.png"))
web.show()
sys.exit(app.exec_())