Peter Kümmel wrote: > This is the Qt message: > QPixmap::operator=: Cannot assign to pixmap during painting > > and happens at ----> > void QWorkArea::resizeEvent(QResizeEvent * resizeEvent) > { > workWidth_ = viewport()->width(); > workHeight_ = viewport()->height(); > > verticalScrollBar()->setPageStep(viewport()->height()); > > // screen_device_ = QPixmap(viewport()->width(), viewport()->height()); > // paint_device_ = QImage(viewport()->width(), viewport()->height(), > QImage::Format_RGB32); > ----> paint_device_ = QPixmap(viewport()->width(), viewport()->height());
The assignment fails because on the old QPixmap painting is still active. But why is painting sometime active? After hours of debugging I've found the reason. The Qt doc states for QPainter::begin: "The errors that can occur are serious problems, such as these: p->begin( 0 ); // impossible - paint device cannot be 0 QPixmap pm( 0, 0 ); p->begin( pm ); // impossible - pm.isNull(); p->begin( myWidget ); p2->begin( myWidget ); // impossible - only one painter at a time Note that most of the time, you can use one of the constructors instead of begin(), and that end() is automatically done at destruction. Warning: A paint device can only be painted by one painter at a time." But in QLPainter -hidden by a nested call- this code is effectively executed, QPainter qp(qwa_->paintDevice()); QPainter qp2(qwa_->paintDevice()); which contradicts "p->begin( myWidget ); p2->begin( myWidget ); // impossible - only one painter at a time" of the doc. And there is NO warning from Qt! So, this is the patch which fixes the resize bug: @@ -225,9 +229,6 @@ void QLPainter::text(int x, int y, char const * s, size_t ls, LyXFont const & f) { - QPainter qp(qwa_->paintDevice()); - setQPainterPen(qp, f.realColor()); - Encoding const * encoding = f.language()->encoding(); if (f.isSymbolFont()) encoding = encodings.symbol_encoding(); @@ -242,6 +243,8 @@ str = ' ' + str; if (f.realShape() != LyXFont::SMALLCAPS_SHAPE) { + QPainter qp(qwa_->paintDevice()); + setQPainterPen(qp, f.realColor()); qp.setFont(fontloader.get(f)); // We need to draw the text as LTR as we use our own bidi // code. And here are some cleanups: - setQPainterPen needs not to return its parameter QPainter& - split painting commands into two lines - color is 'col' - use operator[] Index: frontends/qt4/QLPainter.C =================================================================== --- frontends/qt4/QLPainter.C (revision 14094) +++ frontends/qt4/QLPainter.C (working copy) @@ -55,19 +55,19 @@ return qwa_->viewport()->height(); } -QPainter & QLPainter::setQPainterPen(QPainter & qp, LColor_color c, +void QLPainter::setQPainterPen(QPainter & qp, LColor_color col, Painter::line_style ls, Painter::line_width lw) { - if (c == current_color_ && ls == current_ls_ && lw == current_lw_) - return qp; + if (col == current_color_ && ls == current_ls_ && lw == current_lw_) + return; - current_color_ = c; + current_color_ = col; current_ls_ = ls; current_lw_ = lw; QPen pen = qp.pen(); - pen.setColor(lcolorcache.get(c)); + pen.setColor(lcolorcache.get(col)); switch (ls) { case line_solid: pen.setStyle(Qt::SolidLine); break; @@ -80,14 +80,13 @@ } qp.setPen(pen); - - return qp; } -void QLPainter::point(int x, int y, LColor_color c) +void QLPainter::point(int x, int y, LColor_color col) { QPainter qp(qwa_->paintDevice()); - setQPainterPen(qp, c).drawPoint(x, y); + setQPainterPen(qp, col); + qp.drawPoint(x, y); } @@ -97,7 +96,8 @@ line_width lw) { QPainter qp(qwa_->paintDevice()); - setQPainterPen(qp, col, ls, lw).drawLine(x1, y1, x2, y2); + setQPainterPen(qp, col, ls, lw); + qp.drawLine(x1, y1, x2, y2); } @@ -117,7 +117,8 @@ } QPainter qp(qwa_->paintDevice()); - setQPainterPen(qp, col, ls, lw).drawPolyline(points.get(), np); + setQPainterPen(qp, col, ls, lw); + qp.drawPolyline(points.get(), np); } @@ -127,7 +128,8 @@ line_width lw) { QPainter qp(qwa_->paintDevice()); - setQPainterPen(qp, col, ls, lw).drawRect(x, y, w, h); + setQPainterPen(qp, col, ls, lw); + qp.drawRect(x, y, w, h); } @@ -162,7 +164,8 @@ { // LyX usings 1/64ths degree, Qt usings 1/16th QPainter qp(qwa_->paintDevice()); - setQPainterPen(qp, col).drawArc(x, y, w, h, a1 / 4, a2 / 4); + setQPainterPen(qp, col); + qp.drawArc(x, y, w, h, a1 / 4, a2 / 4); } @@ -204,11 +207,12 @@ QFontMetrics const & qsmallfontm = QFontMetrics(qsmallfont); QPainter qp(qwa_->paintDevice()); + setQPainterPen(qp, f.realColor()); int tmpx = x; size_t ls = s.length(); for (size_t i = 0; i < ls; ++i) { // Brain-dead MSVC wants at(i) rather than operator[] - QChar const c = s.at(i).upper(); + QChar const c = s[i].upper(); if (c != s.at(i)) { qp.setFont(qsmallfont); qp.drawText(tmpx, y, c); @@ -225,9 +229,6 @@ void QLPainter::text(int x, int y, char const * s, size_t ls, LyXFont const & f) { - QPainter qp(qwa_->paintDevice()); - setQPainterPen(qp, f.realColor()); - Encoding const * encoding = f.language()->encoding(); if (f.isSymbolFont()) encoding = encodings.symbol_encoding(); @@ -242,6 +243,8 @@ str = ' ' + str; if (f.realShape() != LyXFont::SMALLCAPS_SHAPE) { + QPainter qp(qwa_->paintDevice()); + setQPainterPen(qp, f.realColor()); qp.setFont(fontloader.get(f)); // We need to draw the text as LTR as we use our own bidi // code. Index: frontends/qt4/QLPainter.h =================================================================== --- frontends/qt4/QLPainter.h (revision 14094) +++ frontends/qt4/QLPainter.h (working copy) @@ -138,7 +138,7 @@ QString const & str, LyXFont const & f); /// set pen parameters - QPainter & setQPainterPen(QPainter & qp, LColor_color c, + void setQPainterPen(QPainter & qp, LColor_color c, line_style ls = line_solid, line_width lw = line_thin);