PDA

View Full Version : QPainter crash when generating icon after drag-drop



craigTheBrit
13th November 2010, 11:48
I have a series of QButton subclasses between which drag-drop operations can be performed. Each button has text and an icon, which is simply a badge with one or two characters (usually a number):



QIcon GMScriptCenter::badgeIcon(const QSize &size, const QColor &outlineColor, const QColor &fillColor, const QString &badgeText)
{
QPixmap pixmap(size);
pixmap.fill(Qt::transparent);
QPainter painter(&pixmap);
painter.setRenderHint(QPainter::Antialiasing);

painter.setPen(QPen(outlineColor));
int minWH = qMax(qMin(size.width(), size.height()), 1);
QRect rect(QPoint(0, 0), size);
painter.setBrush(QBrush(fillColor)); // commenting either this, or...
painter.drawRoundedRect(rect.adjusted(1, 1, -1, -1), minWH/5, minWH/5); // ...this prevents crash

if (!badgeText.isNull()) {
painter.setFont(QFont("Trebuchet MS", size.height()-10));
painter.setPen(QPen(Qt::white));
painter.drawText(rect, badgeText, QTextOption(Qt::AlignCenter));
}

return QIcon(pixmap);
}


Usually, I can call this function to generate an icon and it works fine. But in one circumstance, it does not. After an accepted "drop", in the dropEvent method of my button subclass, I call:


this->setIcon(GMScriptCenter::shared().badgeIcon(QSize(t his->iconSize()), Qt::darkBlue, QColor(0, 80, 180, 200), "1"));

It crashes! And bizarrely, it doesn't crash if I comment out either the setBrush or drawRoundedRect lines. I can generate this badge with just a frame and text and it's fine. It's when I try to use that brush...

What on earth could be happening? Is this a thread-related issue?

high_flyer
15th November 2010, 09:30
QIcon takes a const reference to a pixmap.
And when you return from the slot, your pixmap is destroyed, leaving the reference invalid.
To test this, make your pixmap static and see if it still crashes.
If it does not, better change the pixmap from static to a member, or create it on the heap.

craigTheBrit
15th November 2010, 15:13
That does indeed prevent a crash. I thought I had solved it by moving the update() call that was coming from a successful drop on the target side to just after [QDrag]->exec() on the source side (using the drop target from QDrag info).

Now you've made me think about what's happening here more carefully. Does that mean that the QIcon keeps hold of the QPixmap? If I do create it on the heap, who's reponsible for deleting it? Apologies if this seems like a daft question...

high_flyer
16th November 2010, 08:52
Does that mean that the QIcon keeps hold of the QPixmap?
No, it means exactly the opposite.
If the QIcon had its own deep copy, it wouldn't need the external pixmap object to stay alive.


If I do create it on the heap, who's reponsible for deleting it? Apologies if this seems like a daft question...
Not darf at all, would be better if more people would think that far to ask it.
The answer depends on how you allocate your pixmap.
If you give it a QObject parent, you don't have to worry about destruction, the parent will.
If its parent-less, you will have to take care of deleting it.