PDA

View Full Version : Problem with QPrintPreviewWidget



nifei
5th March 2009, 09:20
The difference between the following codes are indicated by comments, ignore the layout arrangement.
This crashes to: "Access violation reading location 0xcdcdcdd1." in QPicture::play(QPainter *painter), the picture is null.


QPrintPreviewWidget *testPreview_1 = new QPrintPreviewWidget();
QPrintPreviewWidget *testPreview_2 = new QPrintPreviewWidget();
QPushButton *btn_1 = new QPushButton("zoomIn_1");
QPushButton *btn_2 = new QPushButton("zoomIn_2");
//doing layouts

connect(testPreview_2, SIGNAL(paintRequested(QPrinter*)),
this, SLOT(testSlot(QPrinter*)));
connect(testPreview_1, SIGNAL(paintRequested(QPrinter*)),
this, SLOT(testSlot(QPrinter*)));


I removed the second connection to render printer's contents, and it works well


QPrintPreviewWidget *testPreview_1 = new QPrintPreviewWidget();
QPrintPreviewWidget *testPreview_2 = new QPrintPreviewWidget();
QPushButton *btn_1 = new QPushButton("zoomIn_1");
QPushButton *btn_2 = new QPushButton("zoomIn_2");
//doing layouts

connect(testPreview_2, SIGNAL(paintRequested(QPrinter*)),
this, SLOT(testSlot(QPrinter*)));
// connect(testPreview_1, SIGNAL(paintRequested(QPrinter*)),
// this, SLOT(testSlot(QPrinter*)));


Or else, i removed the buttons, leave 2 print preview widget only, and it works well, too. 2 QPrintpreviewWidget are shown side by side.


QPrintPreviewWidget *testPreview_1 = new QPrintPreviewWidget();
QPrintPreviewWidget *testPreview_2 = new QPrintPreviewWidget();
// QPushButton *btn_1 = new QPushButton("zoomIn_1");
// QPushButton *btn_2 = new QPushButton("zoomIn_2");
//doing layouts

connect(testPreview_2, SIGNAL(paintRequested(QPrinter*)),
this, SLOT(testSlot(QPrinter*)));
connect(testPreview_1, SIGNAL(paintRequested(QPrinter*)),
this, SLOT(testSlot(QPrinter*)));


Who has ever came across this problem? is this a but of Qt?

Matriarch
23rd March 2012, 21:27
Same problem here, imo problem appears, when you are drawining "parallel" into two QPrintPreviewWidget. I took a short look inside QPrintPreviewWidget and magic buildin QPrinter::setPreviewMode etc.. and it is really hacked (QPicture). You have to make sure, that you are using only one QPrintPreviewWidget in same time. If it is for small page range, for example 1..5 its no problem in 99.9%, but when I needed to preview a lot of pages (about 150 probably), the painting crashed. If you really need to use 2 QPrintPreviewWidget in "parallel", use QWidget::setUpdatesEnabled(false) to control painting times, it resolved that problem for me.

ChrisW67
25th March 2012, 01:18
Please provide a self-contained, compilable example that crashes. The code below has been running for an hour, zooming and moving every second in two previews of 150 pages, without issue on my machine (Linux Qt 4.7.4):


#include <QtGui>
#include <QDebug>

class Widget: public QWidget {
Q_OBJECT
public:
Widget(QWidget *p = 0): QWidget(p) {
QFile file("lipsum.txt");
if (file.open(QIODevice::ReadOnly)) {
m_lipsum = file.readAll();
}

m_preview1 = new QPrintPreviewWidget(this);
m_preview2 = new QPrintPreviewWidget(this);
QHBoxLayout *layout = new QHBoxLayout(this);
layout->addWidget(m_preview1);
layout->addWidget(m_preview2);
setLayout(layout);

connect(m_preview1, SIGNAL(paintRequested(QPrinter*)), SLOT(doPaint(QPrinter*)));
connect(m_preview2, SIGNAL(paintRequested(QPrinter*)), SLOT(doPaint(QPrinter*)));

// Now make something happen routinely
QTimer *timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), SLOT(doStuff()));
timer->start(1000);
}


public slots:
void doPaint(QPrinter *printer) {
qDebug() << Q_FUNC_INFO << sender();
static const QFont small("Arial", 10);
static const QFont large("Arial", 32);
QPainter p;
if (p.begin(printer)) {
for (int i = 0; i < 150; ++i) {
p.save();
p.setFont(large);
p.drawText(100, 100, QString::number(i));
p.translate(0, 200);
p.setFont(small);
p.drawText(p.window(), m_lipsum);
printer->newPage();
p.restore();
}
}
}

void doStuff() {
static int count = 0;
m_preview1->setZoomFactor(0.5 + (count % 7) * 0.1);
m_preview1->setCurrentPage(count % 23);
m_preview2->setZoomFactor( 0.5 + (count % 13) * 0.1);
m_preview2->setCurrentPage(count % 19);
++count;
}

private:
QString m_lipsum;
QPrintPreviewWidget *m_preview1;
QPrintPreviewWidget *m_preview2;
};

int main(int argc, char *argv[])
{
QApplication app(argc, argv);

Widget w;
w.show();
return app.exec();
}
#include "main.moc"


lipsum.txt is 5 fine paragraphs of gibberish from http://www.lipsum.com
Painting is requested only once for each preview.