Reputation: 41
Im trying to send a PIL image using a print button (self.printBtn.clicked.connect(self.do_printout) ...) from my PYQt5.
The problem is that the main window closes if I press "Cancel" and also when I press "Print". Closing the subroutine using app.exec() was also not successful. (Python 3.7, PyQT5 and Windows OS)
import sys
from PyQt5 import QtGui, QtWidgets, QtPrintSupport
from PyQt5.QtGui import QPixmap
from PyQt5 import QtCore
from PIL import Image
from PIL.ImageQt import ImageQt
class App():
def __init__(self, im):
super().__init__()
self.im = im
dialog = QtPrintSupport.QPrintDialog()
printer = QtPrintSupport.QPrinter()
if dialog.exec_() == QtWidgets.QDialog.Accepted:
self.handle_paint_request(printer, im)
def handle_paint_request(self, printer, im):
printer.setOrientation(QtPrintSupport.QPrinter.Landscape)
printer.setPaperSize(QtPrintSupport.QPrinter.A4)
printer.setPageSize(QtPrintSupport.QPrinter.A4)
printer.setPageMargins(0, 0, 0, 0, QtPrintSupport.QPrinter.Millimeter)
painter = QtGui.QPainter(printer)
painter.begin(printer)
im = ImageQt(im)
image = QtGui.QPixmap.fromImage(im)
screen = image
painter.drawPixmap(10, 10, screen)
painter.end()
def do_print(im):
app = QtWidgets.QApplication(sys.argv)
gui = App(im)
if __name__ == '__main__':
im = Image.open("shot.png").convert("RGB")
do_print(im)
I tried different approaches - using win32print, win32ui, win32gui could be an alternative: if you have knowledge to print PIL image this way let me know. Timgolden was nor working for me (http://timgolden.me.uk/python/win32_how_do_i/print.html). I dont want to use other gui packages just for printing. Important is to be able to select the printer using a PrinterDialog. Thx for your help!
Here is a more complete setup:
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QLabel, QPushButton
from PyQt5.QtGui import QIcon, QPixmap
from PyQt5 import QtGui, QtWidgets, QtPrintSupport, QtCore
from PIL import Image
from PIL.ImageQt import ImageQt
class App(QWidget):
def __init__(self, im):
super().__init__()
self.title = 'PyQt5 image'
self.left = 100
self.top = 100
self.width = 640
self.height = 480
self.im = im
self.setWindowTitle(self.title)
self.setGeometry(self.left, self.top, self.width, self.height)
label = QLabel(self)
qim = ImageQt(self.im).copy()
self.im = QtGui.QPixmap.fromImage(qim)
print(type(self.im))
label.setPixmap(self.im)
self.resize(self.im.width(), self.im.height())
cb = QPushButton('Print', self)
cb.move(self.width, self.height +200)
cb.setGeometry(QtCore.QRect(0, 550, 799, 40))
cb.clicked.connect(self.show_cat)
self.show()
def show_cat(self):
printer = QtPrintSupport.QPrinter()
dialog = QtPrintSupport.QPrintDialog(printer)
if dialog.exec_() == QtWidgets.QDialog.Accepted:
self.handle_paint_request(printer)
def handle_paint_request(self, printer):
printer.setOrientation(QtPrintSupport.QPrinter.Landscape)
printer.setPaperSize(QtPrintSupport.QPrinter.A4)
printer.setPageSize(QtPrintSupport.QPrinter.A4)
printer.setPageMargins(0, 0, 0, 0, QtPrintSupport.QPrinter.Millimeter)
# Create painter
painter = QtGui.QPainter(printer) # Start painter
painter.drawPixmap(10, 10, self.im)
painter.end()
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.resize(506, 312)
self.centralwidget = QtWidgets.QWidget(MainWindow)
# adding pushbutton
self.pushButton = QtWidgets.QPushButton(self.centralwidget)
self.pushButton.setText("Print")
self.pushButton.setGeometry(QtCore.QRect(200, 150, 93, 28))
# adding signal and slot
self.pushButton.clicked.connect(self.do_print)
MainWindow.setCentralWidget(self.centralwidget)
#self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def do_print(self):
app = QApplication(sys.argv)
im = Image.open("shot.png").convert("RGB")
ex = App(im)
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
Upvotes: 0
Views: 900
Reputation: 243955
ou have to set the QPrinter in the QPrintDialog, also painter = QtGui.QPainter(print)
andpainter = QtGui.QPainter() painter.begin(printer)
are equivalent so you should only use one of these options
import sys
from PyQt5 import QtCore, QtGui, QtWidgets, QtPrintSupport
from PIL import Image
from PIL.ImageQt import ImageQt
class App:
def __init__(self, im):
printer = QtPrintSupport.QPrinter()
dialog = QtPrintSupport.QPrintDialog(printer)
if dialog.exec_() == QtWidgets.QDialog.Accepted:
self.handle_paint_request(printer, im)
def handle_paint_request(self, printer, im):
printer.setOrientation(QtPrintSupport.QPrinter.Landscape)
printer.setPaperSize(QtPrintSupport.QPrinter.A4)
printer.setPageSize(QtPrintSupport.QPrinter.A4)
printer.setPageMargins(0, 0, 0, 0, QtPrintSupport.QPrinter.Millimeter)
im = ImageQt(im).copy()
painter = QtGui.QPainter(printer)
image = QtGui.QPixmap.fromImage(im)
painter.drawPixmap(10, 10, image)
painter.end()
def do_print(im):
app = QtWidgets.QApplication(sys.argv)
gui = App(im)
if __name__ == "__main__":
im = Image.open("shot.png").convert("RGB")
do_print(im)
Update:
The new code has other problems compared to the initial code, which are:
On the other hand, you should not modify the class generated by Qt Designer but use it as an interface for another class, considering the above then the solution is:
import sys
from PyQt5 import QtCore, QtGui, QtWidgets, QtPrintSupport
from PIL import Image
from PIL.ImageQt import ImageQt
class App(QtWidgets.QWidget):
def __init__(self, im):
super().__init__()
self.title = "PyQt5 image"
self.left = 100
self.top = 100
self.width = 640
self.height = 480
self.im = im
self.setWindowTitle(self.title)
self.setGeometry(self.left, self.top, self.width, self.height)
label = QtWidgets.QLabel(self)
qim = ImageQt(self.im).copy()
self.im = QtGui.QPixmap.fromImage(qim)
print(type(self.im))
label.setPixmap(self.im)
self.resize(self.im.width(), self.im.height())
cb = QtWidgets.QPushButton("Print", self)
cb.move(self.width, self.height + 200)
cb.setGeometry(QtCore.QRect(0, 550, 799, 40))
cb.clicked.connect(self.show_cat)
self.resize(800, 600)
self.show()
def show_cat(self):
printer = QtPrintSupport.QPrinter()
dialog = QtPrintSupport.QPrintDialog(printer)
if dialog.exec_() == QtWidgets.QDialog.Accepted:
# pass
self.handle_paint_request(printer)
def handle_paint_request(self, printer):
printer.setOrientation(QtPrintSupport.QPrinter.Landscape)
printer.setPaperSize(QtPrintSupport.QPrinter.A4)
printer.setPageSize(QtPrintSupport.QPrinter.A4)
printer.setPageMargins(0, 0, 0, 0, QtPrintSupport.QPrinter.Millimeter)
# Create painter
painter = QtGui.QPainter(printer) # Start painter
painter.drawPixmap(10, 10, self.im)
painter.end()
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.resize(506, 312)
self.centralwidget = QtWidgets.QWidget(MainWindow)
# adding pushbutton
self.pushButton = QtWidgets.QPushButton(self.centralwidget)
self.pushButton.setGeometry(QtCore.QRect(200, 150, 93, 28))
self.label = QtWidgets.QLabel(self.centralwidget)
self.label.setGeometry(QtCore.QRect(140, 90, 221, 20))
self.label.setText("")
MainWindow.setCentralWidget(self.centralwidget)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.pushButton.setText(_translate("MainWindow", "Push Button"))
class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
def __init__(self, parent=None):
super().__init__(parent)
self.setupUi(self)
self.pushButton.clicked.connect(self.do_print)
def do_print(self):
im = Image.open("shot.png").convert("RGB")
self.ex = App(im)
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())
Upvotes: 1