[PyQt] QTableView printing problem

gralex gralex1974 at rambler.ru
Tue Sep 30 19:36:43 BST 2008


Hi, everybody.

I try modify the example "pixelator.pyw" from PyQt4 examples, and don't
understand , why printer spits out a blank sheet.
My variant :

import sys
from PyQt4 import QtCore, QtGui

import pixelator_rc


ItemSize = 256


class PixelDelegate(QtGui.QAbstractItemDelegate):
     def __init__(self, parent=None):
         QtGui.QAbstractItemDelegate.__init__(self,parent)

         self.pixelSize = 12

     def paint(self, painter, option, index):
         painter.setRenderHint(QtGui.QPainter.Antialiasing)
         painter.setPen(QtCore.Qt.NoPen)

         if option.state & QtGui.QStyle.State_Selected:
             painter.setBrush(option.palette.highlight())
         else:
             painter.setBrush(QtGui.QBrush(QtCore.Qt.white))

         painter.drawRect(option.rect)

         if option.state & QtGui.QStyle.State_Selected:
             painter.setBrush(option.palette.highlightedText())
         else:
             painter.setBrush(QtGui.QBrush(QtCore.Qt.black))

         size = min(option.rect.width(), option.rect.height())
         brightness, ok = index.model().data(index, 
QtCore.Qt.DisplayRole).toInt()
         radius = (size/2.0) - (brightness/255.0 * size/2.0)
         painter.drawEllipse(QtCore.QRectF(
                             option.rect.x() + option.rect.width()/2 - 
radius,
                             option.rect.y() + option.rect.height()/2 - 
radius,
                             2*radius, 2*radius))

     def sizeHint(self, option, index):
         return QtCore.QSize(self.pixelSize, self.pixelSize)

     def setPixelSize(self, size):
         self.pixelSize = size


class ImageModel(QtCore.QAbstractTableModel):
     def __init__(self, image, parent=None):
         QtCore.QAbstractTableModel.__init__(self, parent)

         self.modelImage = QtGui.QImage(image)

     def rowCount(self, parent):
         return self.modelImage.height()

     def columnCount(self, parent):
         return self.modelImage.width()

     def data(self, index, role):
         if not index.isValid():
             return QtCore.QVariant()
         elif role != QtCore.Qt.DisplayRole:
             return QtCore.QVariant()

         return 
QtCore.QVariant(QtGui.qGray(self.modelImage.pixel(index.column(), 
index.row())))


class MainWindow(QtGui.QMainWindow):
     def __init__(self, parent=None):
         QtGui.QMainWindow.__init__(self, parent)

         self.currentPath = QtCore.QDir.home().absolutePath()
         self.model = ImageModel(QtGui.QImage(), self)

         centralWidget = QtGui.QWidget()

         self.view = QtGui.QTableView()
         #self.view.setShowGrid(False)
         #self.view.horizontalHeader().hide()
         #self.view.verticalHeader().hide()

         delegate = PixelDelegate(self)
         #self.view.setItemDelegate(delegate)

         pixelSizeLabel = QtGui.QLabel(self.tr("Pixel size:"))
         pixelSizeSpinBox = QtGui.QSpinBox()
         pixelSizeSpinBox.setMinimum(1)
         pixelSizeSpinBox.setMaximum(32)
         pixelSizeSpinBox.setValue(12)

         fileMenu = QtGui.QMenu(self.tr("&File"), self)
         openAction = fileMenu.addAction(self.tr("&Open..."))
         openAction.setShortcut(QtGui.QKeySequence(self.tr("Ctrl+O")))

         self.printAction = fileMenu.addAction(self.tr("&Print..."))
         self.printAction.setEnabled(False)
         self.printAction.setShortcut(QtGui.QKeySequence(self.tr("Ctrl+P")))

         quitAction = fileMenu.addAction(self.tr("E&xit"))
         quitAction.setShortcut(QtGui.QKeySequence(self.tr("Ctrl+Q")))

         helpMenu = QtGui.QMenu(self.tr("&Help"), self)
         aboutAction = helpMenu.addAction(self.tr("&About"))

         self.menuBar().addMenu(fileMenu)
         self.menuBar().addSeparator()
         self.menuBar().addMenu(helpMenu)

         self.connect(openAction, QtCore.SIGNAL("triggered()"),
                      self.chooseImage)
         self.connect(self.printAction, QtCore.SIGNAL("triggered()"),
                      self.printImage)
         self.connect(quitAction, QtCore.SIGNAL("triggered()"),
                      QtGui.qApp, QtCore.SLOT("quit()"))
         self.connect(aboutAction, QtCore.SIGNAL("triggered()"),
                      self.showAboutBox)
         self.connect(pixelSizeSpinBox, QtCore.SIGNAL("valueChanged(int)"),
                      delegate.setPixelSize)
         self.connect(pixelSizeSpinBox, QtCore.SIGNAL("valueChanged(int)"),
                      self.updateView)

         controlsLayout = QtGui.QHBoxLayout()
         controlsLayout.addWidget(pixelSizeLabel)
         controlsLayout.addWidget(pixelSizeSpinBox)
         controlsLayout.addStretch(1)

         mainLayout = QtGui.QVBoxLayout()
         mainLayout.addWidget(self.view)
         mainLayout.addLayout(controlsLayout)
         centralWidget.setLayout(mainLayout)

         self.setCentralWidget(centralWidget)

         self.setWindowTitle(self.tr("Pixelator"))
         self.resize(640,480)

     def chooseImage(self):
         fileName = QtGui.QFileDialog.getOpenFileName(self, 
self.tr("Choose an Image"),
                                                      self.currentPath, "*")

         if not fileName.isEmpty():
             self.openImage(fileName)

     def openImage(self, fileName):
         image = QtGui.QImage()

         if image.load(fileName):
             newModel = ImageModel(image, self)
             self.view.setModel(newModel)
             self.model = newModel

             if not fileName.startsWith(":/"):
                 self.currentPath = fileName
                 self.setWindowTitle(self.tr("%1 - 
Pixelator").arg(self.currentPath))

             self.printAction.setEnabled(True)
             self.updateView()

     def printImage(self):
         if self.model.rowCount(QtCore.QModelIndex()) * 
self.model.columnCount(QtCore.QModelIndex()) > 90000:
             answer = QtGui.QMessageBox.question(self, self.tr("Large 
Image Size"),
                                   self.tr("The printed image may be very "
                                           "large. Are you sure that you 
want "
                                           "to print it?"),
                                   QtGui.QMessageBox.Yes, 
QtGui.QMessageBox.No)
             if answer == QtGui.QMessageBox.No:
                 return

         printer = QtGui.QPrinter(QtGui.QPrinter.HighResolution)

         dlg = QtGui.QPrintDialog(printer, self)
         dlg.setWindowTitle(self.tr("Print Image"))

         if dlg.exec_() != QtGui.QDialog.Accepted:
             return

         painter = QtGui.QPainter()
         painter.begin(printer)

         rows = self.model.rowCount(QtCore.QModelIndex())
         columns = self.model.columnCount(QtCore.QModelIndex())
         sourceWidth = (columns+1) * ItemSize
         sourceHeight = (rows+1) * ItemSize

         painter.save()

         xscale = printer.pageRect().width() / float(sourceWidth)
         yscale = printer.pageRect().height() / float(sourceHeight)
         scale = min(xscale, yscale)

 
painter.translate(printer.pageRect().x()+printer.pageRect().width()/2,
 
printer.pageRect().y()+printer.pageRect().height()/2)
         painter.scale(scale, scale)
         painter.translate(-sourceWidth/2, -sourceHeight/2)

         option = QtGui.QStyleOptionViewItem()
         parent = QtCore.QModelIndex()

         progress = QtGui.QProgressDialog(self.tr("Printing..."), 
self.tr("Cancel..."), 0, rows, self)
         y = ItemSize / 2.0

         for row in range(rows):
             progress.setValue(row)
             QtGui.qApp.processEvents()
             if progress.wasCanceled():
                 break

             x = ItemSize / 2.0

             for col in range(columns):
                 option.rect = QtCore.QRect(x, y, ItemSize, ItemSize)
                 self.view.itemDelegate().paint(painter, option,
                                              self.model.index(row, col, 
parent))
                 x = x + ItemSize

             y = y + ItemSize

         progress.setValue(rows)

         painter.restore()
         painter.end()

         if progress.wasCanceled():
             QtGui.QMessageBox.information(self, self.tr("Printing 
canceled"),
                                           self.tr("The printing process 
was canceled."),
                                           QtGui.QMessageBox.Cancel)

     def showAboutBox(self):
         QtGui.QMessageBox.about(self, self.tr("About the Pixelator 
example"),
             self.tr("This example demonstrates how a standard view and 
a custom\n"
                     "delegate can be used to produce a specialized 
representation\n"
                     "of data in a simple custom model."))

     def updateView(self):
         for row in range(self.model.rowCount(QtCore.QModelIndex())):
             self.view.resizeRowToContents(row)
         for column in range(self.model.columnCount(QtCore.QModelIndex())):
             self.view.resizeColumnToContents(column)


if __name__ == "__main__":
     app = QtGui.QApplication(sys.argv)
     window = MainWindow()
     window.show()
     window.openImage(QtCore.QString(":/images/qt.png"))
     sys.exit(app.exec_())


Sorry for my english.
Good luck.
Gralex



More information about the PyQt mailing list