PDA

View Full Version : QPrinter / QPrintDialog issue



d_stranz
4th June 2014, 01:01
Using Qt 5.2 on Windows 7 64bit. I am building a 32-bit app

I am trying to get printing working. I have a weird problem that I can't seem to figure out. If I create a QPrinter instance using this code:


QPrinter * pPrinter = new QPrinter( QPrinterInfo::defaultPrinter(), QPrinter::ScreenResolution );

and then look at the values for
QPrinter::pageRect( QPrinter::Inch ) and QPrinter::paperRect( QPrinter::Inch ) I get the results I would expect for my default printer (Letter size paper, 8.5 x 11 inches).

If I then pass this QPrinter instance to QPrintDialog and open it:



if ( pPrinter && pPrinter->isValid() )
{
QPrintDialog dlg( pPrinter );
dlg.setOptions( QAbstractPrintDialog::None );

connect( &dlg, SIGNAL( accepted( QPrinter * ) ), this, SLOT( onPrinterAccepted( QPrinter * ) ) );
dlg.exec();
}


and then examine those same values in the onPrinterAccepted() slot, those values are now completely messed up, typically QRectF( 0.0, 0.0, -0.0104166, -0.0104166)

This happens even if I do nothing at all with the dialog - let it display, don't do anything except click the "Print" button.

If I create the QPrintDialog without passing it a QPrinter instance:



QPrintDialog dlg;
dlg.setOptions( QAbstractPrintDialog::None );

connect( &dlg, SIGNAL( accepted( QPrinter * ) ), this, SLOT( onPrinterAccepted( QPrinter * ) ) );
dlg.exec();


I get exactly the same behavior. If I select a different printer from the dialog, it doesn't matter what printer I choose, I still get the same messed up results if I let the dialog use my QPrinter instance or if I look at the one returned to the slot.

Changing the Unit type in the call to
QPrinter::pageRect() results in different values being returned, but they are always wrong and always a negative height and width.

I have confirmed that there is only one plugins/printsupport directory on my machine, so it can't be pulling in a mis-matched "windowsprintersupport" DLL

I do not know if it is relevant, but the code that does the printing is in a static library, linked into my app. The Print QAction's triggered() signal in the GUI is connected to a slot in the library that kicks off the printing.

Any ideas what I might be doing wrong?

d_stranz
4th June 2014, 22:55
Here's a minimal compilable example to demonstrate the problem. I have attached the PNG file to this post. With the QPrintDialog code commented out (as shown below), I get the results in the attached PDF file using PDFCreator as my default printer.

I would greatly appreciate it if someone could run this code and tell me if it also fails for you when you allow the QPrintDialog code to execute.



// PrintingTestDlg.h:

#ifndef PRINTINGTESTDLG_H
#define PRINTINGTESTDLG_H

#include <QDialog>

class QPrinter;
class QLabel;

class PrintingTestDlg : public QDialog
{
Q_OBJECT

public:
PrintingTestDlg(QWidget *parent = 0);
~PrintingTestDlg();

protected slots:
void onPrint();
void onPrinterAccepted( QPrinter * pPrinter );

private:
QLabel * mpLabel;
};

#endif // PRINTINGTESTDLG_H




// PrintingTestDlg.cpp:

#include "PrintingTestDlg.h"

#include <QHBoxLayout>
#include <QPixmap>
#include <QLabel>
#include <QPushButton>
#include <QPrinter>
#include <QPrinterInfo>
#include <QPrintDialog>
#include <QPainter>

PrintingTestDlg::PrintingTestDlg(QWidget *parent)
: QDialog(parent)
{
QHBoxLayout * pLayout = new QHBoxLayout( this );

QPushButton * pPrintBtn = new QPushButton( this );
pPrintBtn->setText( "Print" );

pLayout->addWidget( pPrintBtn );

mpLabel = new QLabel( this ) ;
mpLabel->setPixmap( QPixmap( "./logo11w.png" ) );

pLayout->addWidget( mpLabel );
setLayout( pLayout );

connect( pPrintBtn, SIGNAL( clicked() ), this, SLOT( onPrint() ) );
}

PrintingTestDlg::~PrintingTestDlg()
{
}

void PrintingTestDlg::onPrint()
{
QPrinterInfo printerInfo = QPrinterInfo::defaultPrinter();

QPrinter * pPrinter = 0;
if ( !printerInfo.isNull() )
pPrinter = new QPrinter( printerInfo, QPrinter::ScreenResolution );

if ( pPrinter && pPrinter->isValid() )
{
QPrintDialog dlg( pPrinter );
dlg.setOptions( QAbstractPrintDialog::None );

// With this line un-commented, the printing works correctly for the
// default printer with default settings
onPrinterAccepted( pPrinter );

// Un-comment these two lines, and comment out the line above to see what happens
// when the QPrintDialog is used.
// connect( &dlg, SIGNAL( accepted( QPrinter * ) ), this, SLOT( onPrinterAccepted( QPrinter * ) ) );
// dlg.exec();

delete pPrinter;
}
}

void PrintingTestDlg::onPrinterAccepted( QPrinter * pPrinter )
{
QString printName = pPrinter->printerName();
QRectF paperRect = pPrinter->paperRect( QPrinter::DevicePixel );
QRectF pageRect = pPrinter->pageRect( QPrinter::DevicePixel );
QRect plotRect = mpLabel->rect();

double xscale = pageRect.width() / double( plotRect.width() );
double yscale = pageRect.height() / double( plotRect.height() );
double scale = qMin( xscale, yscale );

QPainter painter( pPrinter );
painter.translate( paperRect.x() + pageRect.width() / 2,
paperRect.y() + pageRect.height() / 2 );
painter.scale( scale, scale );
painter.translate( -plotRect.width() / 2, -plotRect.height() / 2 );

mpLabel->render( &painter );
}