Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. Qt for Python
  4. Printing html using QWebEngineView fails (PyQt5)
Forum Update on Monday, May 27th 2025

Printing html using QWebEngineView fails (PyQt5)

Scheduled Pinned Locked Moved Solved Qt for Python
pythonqt for python
2 Posts 1 Posters 2.0k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • K Offline
    K Offline
    Koenux
    wrote on 3 May 2020, 13:38 last edited by Koenux 5 Mar 2020, 13:40
    #1

    Hello everyone,

    I'm trying to get print html code which is generated by my application, but unfortunately I can't get it to work.
    The print preview shows the page but the quality looks bad, all I get is a corrupted PDF file and it is kinda slow. I had it working for years with PyQt4.x.

    The code where I call my printer class:

    	def _print(self, preview=False, PDF=False):
    		if(not self.printer.readyState):
    			print('printer class not ready yet.')
    			return;
    
    		tpl = '<html><head></head><body>Test</body></html>';
    
    		self.printer.load();
    		self.printer.forceLandscape = True;
    		self.printer.fontfamily = str(self.cfg.value('fontsettings_0_font'))
    		self.printer.fontsize = str(self.cfg.value('fontsettings_0_size'))
    		self.printer.preview = preview;
    		self.printer.pdf = PDF;
    		self.printer.setHtml(tpl);
    		self.printer.print();
    

    The printer class (printer.py)

    from typing import List
    
    try:
    	import sys, os, locale, subprocess
    	from PyQt5.QtGui import *
    	from PyQt5.QtCore import *
    	from PyQt5.QtNetwork import *	
    	from PyQt5.QtPrintSupport import QPrinter, QPrintPreviewDialog, QPrintDialog
    	from PyQt5 import QtSql, QtGui
    	from PyQt5.QtWidgets import QWidget, QDialog, QTextEdit
    
    	from PyQt5.QtWebEngineWidgets import QWebEngineView,QWebEnginePage,QWebEngineSettings
    
    
    except ImportError as msg:
    	print("Exception: Couldn't import all required modules:\n-> ImportError: ", msg)
    	sys.exit()
    
    locale.setlocale(locale.LC_ALL, '')
    locale.setlocale(locale.LC_NUMERIC, '')
    	
    
    class printer(QWidget):
    	# Initialize printer class
    	def __init__(self, parent=None):
    		QWidget.__init__(self);
    		self.parent = parent;
    		self.pagecounter=-1;
    		self.html="";
    		self.preview=""
    		self.m_page = None
    		self.m_inPrintPreview = False
    		self.page = QWebEnginePage();
    		self.progress = 0;
    		self.waiting = False;
    
    
    		# tasklist
    		self.readyState = True;
    
    		self.defaultPageMargins=[float(self.parent.cfg.value('page_margin_rawdec_left')) \
    		, float(self.parent.cfg.value('page_margin_rawdec_top')) \
    		, float(self.parent.cfg.value('page_margin_rawdec_right')) \
    		, float(self.parent.cfg.value('page_margin_rawdec_bottom')) \
    		, int(self.parent.cfg.value('page_margin_rawdec_unit'))];
    		
    
    	def setPageMargins(self,a,b,c,d,e):
    		self.pageMargins=[a,b,c,d,e];
    		
    	
    	# Load printer for new job
    	def load(self):
    		self.fontfamily='Sans'
    		self.fontsize='12'
    		self.progress = 0;
    		self.pages = [];
    		self.pagecounter=-1;
    		self.forceLandscape=False;
    		self.pageMargins=self.defaultPageMargins;
    
    	def readyTask(self):
    		self.readyState = True;
    
    
    	def pageSetup(self):
    		ps = QPageSetupDialog(self.printer,self.doc);
    		ps.open();
    
    
    
    	def openPDF(self, filename="output.pdf"):
    		if os.name == 'mac':
    			subprocess.call(['open', filename])
    		elif os.name == 'nt':
    			subprocess.call(['start', filename], shell=True)
    		elif os.name == 'posix':
    			subprocess.call(['xdg-open', filename])
    
    
    	def setHtml(self, html):
    		self.page.setHtml(html)
    
    	def pageloaded(self):
    		print('webviewloaded')
    		if(self.waiting):
    			self.waiting = False;
    			return self.print();
    
    	def pageprogress(self,progress):
    		print(progress)
    		self.progress = progress;
    
    	@property
    	def page(self):
     		return self.m_page
    
    	@page.setter
    	def page(self, page):
    		if isinstance(page, QWebEnginePage):
    			self.m_page = page
    			self.page.printRequested.connect(self.printPreview)
    			self.page.loadFinished.connect(self.pageloaded)
    			self.page.loadProgress.connect(self.pageprogress);
    
    		else:
    			raise TypeError("page must be a QWebEnginePage")
    
    
    	def getPrinter(self):
    		pm = self.pageMargins;
    		printer = QPrinter(QPrinter.HighResolution)
    		printer.setPageSize(QPrinter.A4);
    		printer.setFullPage (True); # must be before set margin
    		printer.setPageMargins(pm[0],pm[1],pm[2],pm[3], pm[4]);
    
    		# Landscape or Portraitself.webview.show();
    		if self.forceLandscape:
    			printer.setOrientation(QPrinter.Landscape);
    			self.forceLandscape=False;
    		else:
    			printer.setOrientation(QPrinter.Portrait);
    
    		return printer;
    
    
    
    
    	@pyqtSlot()
    	def print(self):
    		if(self.progress is not 100):
    			self.waiting = True;
    			print('waiting...')
    			print(self.progress)
    			return;
    
    		print('ok')
    
    		if(self.preview):
    			return self.printPreview();
    
    
    		printer = self.getPrinter();
    
    		# PDF
    		tmpfile=None;
    		if(self.pdf):
    			tmpfile = QTemporaryFile();
    			if(tmpfile.open()):
    				print(tmpfile)
    				printer.setOutputFormat(QPrinter.PdfFormat)
    				printer.setOutputFileName(tmpfile.fileName())
    				return self.printDocument(printer,tmpfile)
    			else:
    				debug().critical("NoesAdmin printer.py couldn't open a temporary file.")
    				return False;
    
    		# Print dialog
    		dialog = QPrintDialog(printer, self.page.view())
    		if dialog.exec_() != QDialog.Accepted:
    			self.readyTask();
    			return
    		self.printDocument(printer, tmpfile)
    
    	@pyqtSlot()
    	def printPreview(self):
    		if self.page is None:
    			return
    		if self.m_inPrintPreview:
    			return
    		self.m_inPrintPreview = True
    
    		printer = self.getPrinter();
    		preview = QPrintPreviewDialog(printer,self.page.view())
    		preview.paintRequested.connect(self.printDocument);
    
    		if preview.exec_() != QDialog.Accepted:
    			self.readyTask();
    		self.m_inPrintPreview = False
    
    	@pyqtSlot(QPrinter)
    	def printDocument(self, printer, tmpfile=None):
    		result = False
    		loop = QEventLoop()
    		self.parent.changeStatusBar('Printjob loading...');
    		
    		def printPreview(sucess):
    			nonlocal result
    			result = sucess
    			loop.quit()
    	
    		self.page.print(printer,printPreview)
    		loop.exec_()
    		if not result:
    			print('no result')
    			painter = QPainter()
    			if painter.begin(printer):
    				font = painter.font()
    				font.setPixelSize(20)
    				painter.setFont(font)
    				painter.drawText(QPointF(10, 25), "Could not generate print preview.")
    				painter.end()
    		self.readyTask();
    		self.parent.readyStatusBar();
    
    
    		if self.pdf and tmpfile:
    			print('PDF print opening....');
    			self.openPDF(tmpfile.fileName())
    

    I tried to use QTextDocument as an alternative for QWebEngineView which worked perfectly fine except for the lack of support for modern html and css and I had trouble with the page size, so I rather use webengine if possible.

    Does anyone have an idea where it goes wrong? Sorry if the code is a bit messy.

    Thanks!

    (Qt 5.12.5 - Python 3.7.7)

    1 Reply Last reply
    0
    • K Offline
      K Offline
      Koenux
      wrote on 4 May 2020, 09:54 last edited by
      #2

      I've got a bit further than yesterday with this issue. I went back to the example on this website:
      http://quabr.com:8182/59438021/how-do-i-create-a-print-preview-of-qwebengineview-in-pyqt5

      The problem has to do something with:

      printer = QPrinter(QPrinter.HighResolution)
      

      When I use QPrinter() without the HighResolution part, everything works as expected. I didn't realise that the example had the same problem since it calls the printPreview method which doesn't have the resolution part.

      Is this a bug in (Py)Qt?

      Since my problem is fixed, I'm will mark it as solved.

      1 Reply Last reply
      0

      1/2

      3 May 2020, 13:38

      • Login

      • Login or register to search.
      1 out of 2
      • First post
        1/2
        Last post
      0
      • Categories
      • Recent
      • Tags
      • Popular
      • Users
      • Groups
      • Search
      • Get Qt Extensions
      • Unsolved