python 如何使用QPrinter和QPrintPreviewDialog

z9zf31ra  于 2023-11-16  发布在  Python
关注(0)|答案(2)|浏览(137)

我想使用PyQt通过打印机预览并打印报告。我尝试了以下代码:

printer = QtGui.QPrinter()
doc  = QtGui.QTextDocument("testing")
dialog = QtGui.QPrintDialog(printer)
dialog.setModal(True)
dialog.setWindowTitle("printerrr")
pdialog = QtGui.QPrintPreviewDialog(printer)
pdialog.setWindowFlags(QtCore.Qt.Window)
pdialog.exec_()

字符串
我如何预览我的报告,然后打印它?

6ju8rftf

6ju8rftf1#

Qt打印对话框的基本演示:

更新

下面给出的另一种解决方案是使用Qt WebEngine来渲染和打印文档。这允许除了HTML之外还支持更大范围的文档类型,例如PDF,图像,纯文本等。下面示例中的Printer类基于Qt文档中的WebEngine Widgets PrintMe Example

from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5 import QtPrintSupport, QtWebEngineWidgets

class Window(QtWidgets.QWidget):
    def __init__(self):
        super(Window, self).__init__()
        self.viewer = QtWebEngineWidgets.QWebEngineView(self)
        self.viewer.settings().setAttribute(
            QtWebEngineWidgets.QWebEngineSettings.PluginsEnabled, True)
        self.viewer.settings().setAttribute(
            QtWebEngineWidgets.QWebEngineSettings.PdfViewerEnabled, True)
        self.buttonOpen = QtWidgets.QPushButton('Open', self)
        self.buttonOpen.clicked.connect(self.handleOpen)
        self.buttonPrint = QtWidgets.QPushButton('Print', self)
        self.buttonPrint.clicked.connect(self.handlePrint)
        self.buttonPreview = QtWidgets.QPushButton('Preview', self)
        self.buttonPreview.clicked.connect(self.handlePreview)
        layout = QtWidgets.QGridLayout(self)
        layout.addWidget(self.viewer, 0, 0, 1, 3)
        layout.addWidget(self.buttonOpen, 1, 0)
        layout.addWidget(self.buttonPrint, 1, 1)
        layout.addWidget(self.buttonPreview, 1, 2)
        self.printer = Printer(self.viewer.page(), self)

    def handleOpen(self):
        if path := QtWidgets.QFileDialog.getOpenFileName(self)[0]:
            self.viewer.load(QtCore.QUrl.fromLocalFile(path))

    def handlePrint(self):
        if self.viewer.url().isValid():
            self.printer.print()

    def handlePreview(self):
        if self.viewer.url().isValid():
            self.printer.preview()

class Printer(QtCore.QObject):
    def __init__(self, page, parent=None):
        super().__init__(parent)
        self._page = page
        self._printing = False

    def render(self, printer):
        loop = QtCore.QEventLoop()
        failed = False
        QtWidgets.QApplication.setOverrideCursor(QtCore.Qt.WaitCursor)
        def callback(result):
            nonlocal failed
            failed = not result
            QtWidgets.QApplication.restoreOverrideCursor()
            loop.quit()
        self._page.print(printer, callback)
        loop.exec()
        if failed:
            painter = QtGui.QPainter()
            if painter.begin(printer):
                font = painter.font()
                font.setPixelSize(20)
                painter.setFont(font)
                painter.drawText(QtCore.QPointF(10, 25),
                    'Could not generate print preview')
                painter.end()

    def preview(self):
        if not self._printing:
            self._printing = True
            printer = QtPrintSupport.QPrinter()
            printer.setResolution(300)
            dialog = QtPrintSupport.QPrintPreviewDialog(
                printer, self._page.view())
            dialog.paintRequested.connect(self.render)
            dialog.exec()
            dialog.deleteLater()
            self._printing = False

    def print(self):
        printer = QtPrintSupport.QPrinter(
            QtPrintSupport.QPrinter.HighResolution)
        dialog = QtPrintSupport.QPrintDialog(printer, self._page.view())
        if dialog.exec() == QtWidgets.QDialog.Accepted:
            self.render(printer)
        dialog.deleteLater()

if __name__ == '__main__':

    QtWidgets.QApplication.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling)
    app = QtWidgets.QApplication(['Printing Demo'])
    window = Window()
    window.setGeometry(600, 100, 800, 600)
    window.show()
    app.exec()

字符串
以前的例子:

  • PyQt4*:
import sys, os
    from PyQt4 import QtGui, QtCore
    
    class Window(QtGui.QWidget):
        def __init__(self):
            super(Window, self).__init__()
            self.setWindowTitle('Document Printer')
            self.editor = QtGui.QTextEdit(self)
            self.editor.textChanged.connect(self.handleTextChanged)
            self.buttonOpen = QtGui.QPushButton('Open', self)
            self.buttonOpen.clicked.connect(self.handleOpen)
            self.buttonPrint = QtGui.QPushButton('Print', self)
            self.buttonPrint.clicked.connect(self.handlePrint)
            self.buttonPreview = QtGui.QPushButton('Preview', self)
            self.buttonPreview.clicked.connect(self.handlePreview)
            layout = QtGui.QGridLayout(self)
            layout.addWidget(self.editor, 0, 0, 1, 3)
            layout.addWidget(self.buttonOpen, 1, 0)
            layout.addWidget(self.buttonPrint, 1, 1)
            layout.addWidget(self.buttonPreview, 1, 2)
            self.handleTextChanged()
    
        def handleOpen(self):
            path = QtGui.QFileDialog.getOpenFileName(
                self, 'Open file', '',
                'HTML files (*.html);;Text files (*.txt)')
            if path:
                file = QtCore.QFile(path)
                if file.open(QtCore.QIODevice.ReadOnly):
                    stream = QtCore.QTextStream(file)
                    text = stream.readAll()
                    info = QtCore.QFileInfo(path)
                    if info.completeSuffix() == 'html':
                        self.editor.setHtml(text)
                    else:
                        self.editor.setPlainText(text)
                    file.close()
    
        def handlePrint(self):
            dialog = QtGui.QPrintDialog()
            if dialog.exec_() == QtGui.QDialog.Accepted:
                self.editor.document().print_(dialog.printer())
    
        def handlePreview(self):
            dialog = QtGui.QPrintPreviewDialog()
            dialog.paintRequested.connect(self.editor.print_)
            dialog.exec_()
    
        def handleTextChanged(self):
            enable = not self.editor.document().isEmpty()
            self.buttonPrint.setEnabled(enable)
            self.buttonPreview.setEnabled(enable)
    
    if __name__ == '__main__':
    
        app = QtGui.QApplication(sys.argv)
        window = Window()
        window.resize(640, 480)
        window.show()
        sys.exit(app.exec_())

  • PyQt5*:
import sys, os
from PyQt5 import QtCore, QtWidgets, QtPrintSupport

class Window(QtWidgets.QWidget):
    def __init__(self):
        super(Window, self).__init__()
        self.setWindowTitle('Document Printer')
        self.editor = QtWidgets.QTextEdit(self)
        self.editor.textChanged.connect(self.handleTextChanged)
        self.buttonOpen = QtWidgets.QPushButton('Open', self)
        self.buttonOpen.clicked.connect(self.handleOpen)
        self.buttonPrint = QtWidgets.QPushButton('Print', self)
        self.buttonPrint.clicked.connect(self.handlePrint)
        self.buttonPreview = QtWidgets.QPushButton('Preview', self)
        self.buttonPreview.clicked.connect(self.handlePreview)
        layout = QtWidgets.QGridLayout(self)
        layout.addWidget(self.editor, 0, 0, 1, 3)
        layout.addWidget(self.buttonOpen, 1, 0)
        layout.addWidget(self.buttonPrint, 1, 1)
        layout.addWidget(self.buttonPreview, 1, 2)
        self.handleTextChanged()

    def handleOpen(self):
        path = QtWidgets.QFileDialog.getOpenFileName(
            self, 'Open file', '',
            'HTML files (*.html);;Text files (*.txt)')[0]
        if path:
            file = QtCore.QFile(path)
            if file.open(QtCore.QIODevice.ReadOnly):
                stream = QtCore.QTextStream(file)
                text = stream.readAll()
                info = QtCore.QFileInfo(path)
                if info.completeSuffix() == 'html':
                    self.editor.setHtml(text)
                else:
                    self.editor.setPlainText(text)
                file.close()

    def handlePrint(self):
        dialog = QtPrintSupport.QPrintDialog()
        if dialog.exec_() == QtWidgets.QDialog.Accepted:
            self.editor.document().print_(dialog.printer())

    def handlePreview(self):
        dialog = QtPrintSupport.QPrintPreviewDialog()
        dialog.paintRequested.connect(self.editor.print_)
        dialog.exec_()

    def handleTextChanged(self):
        enable = not self.editor.document().isEmpty()
        self.buttonPrint.setEnabled(enable)
        self.buttonPreview.setEnabled(enable)

if __name__ == '__main__':

    app = QtWidgets.QApplication(sys.argv)
    window = Window()
    window.resize(640, 480)
    window.show()
    sys.exit(app.exec_())


要打印预览图形视图,请使用其render方法:

def handlePreview(self):
    # dialog = QtPrintSupport.QPrintPreviewDialog() # PyQt5
    dialog = QtGui.QPrintPreviewDialog()
    dialog.paintRequested.connect(self.handlePaintRequest)
    dialog.exec_()

def handlePaintRequest(self, printer):
    self.view.render(QtGui.QPainter(printer))

68bkxrlz

68bkxrlz2#

PyQt5对example by ekhumoro的更新,为Chart提供打印预览和打印:

from PyQt5 import QtChart, QtCore, QtGui, QtPrintSupport, QtWidgets 
import sys
import random

class Window(QtWidgets.QWidget):
    def __init__(self):
        QtWidgets.QWidget.__init__(self)
        self.setWindowTitle(self.tr('Chart Printing'))
        self.chart = QtChart.QChart()
        self.chart_view = QtChart.QChartView(self.chart)
        self.chart_view.setRenderHint(QtGui.QPainter.Antialiasing)
        self.buttonPreview = QtWidgets.QPushButton('Preview', self)
        self.buttonPreview.clicked.connect(self.handle_preview)
        self.buttonPrint = QtWidgets.QPushButton('Print', self)
        self.buttonPrint.clicked.connect(self.handle_print)               
        layout = QtWidgets.QGridLayout(self)
        layout.addWidget(self.chart_view, 0, 0, 1, 2)
        layout.addWidget(self.buttonPreview, 1, 0)        
        layout.addWidget(self.buttonPrint, 1, 1)
        self.create_chart()

    def create_chart(self):
        self.chart.setTitle("Chart Print Preview and Print Example") 
        for i in range(5):     
            series = QtChart.QLineSeries()     
            series.setName("Line {}".format(i + 1))
            series.append(0, 0)
            for i in range(1, 10):
                series.append(i, random.randint(1, 9))
            series.append(10, 10)
            self.chart.addSeries(series)
        self.chart.createDefaultAxes() 

    def handle_print(self):
        printer = QtPrintSupport.QPrinter(QtPrintSupport.QPrinter.HighResolution)
        dialog = QtPrintSupport.QPrintDialog(printer, self)
        if dialog.exec_() == QtPrintSupport.QPrintDialog.Accepted:
            self.handle_paint_request(printer)

    def handle_preview(self):
        dialog = QtPrintSupport.QPrintPreviewDialog()
        dialog.paintRequested.connect(self.handle_paint_request)
        dialog.exec_()

    def handle_paint_request(self, printer):
        painter = QtGui.QPainter(printer)
        painter.setViewport(self.chart_view.rect())
        painter.setWindow(self.chart_view.rect())                        
        self.chart_view.render(painter)
        painter.end()

if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    window = Window()
    window.resize(640, 480)
    window.show()
    sys.exit(app.exec_())

字符串
编辑:要在Windows上运行上述演示代码,则需要:

> pip install PyQt5  
> pip install pyqt5-tools   
> pip install PyQtChart

相关问题