QPixmap's loadFromData function used some strange mechanism for cache?

526 views Asked by At

There is a strange phenomenon on QPixmap's loadFromData function. This is the case:

QPixmap pix1(":/test1.png");    
QPixmap pix2(":/test2.png");
ui->labelPix1>setPixmap(pix1);
pix1 = pix2;
ui->labelPix2->setPixmap(pix1);

In the code above, the tow label controls have loaded the same QPixmap object pix1, but pix1 had been changed before labelPix2 load it, so the tow labels show different images(test1.png and test2.png), it's right.

Then we change the line "pix1 = pix2", use the following block to instead:

QByteArray ba;
QBuffer buf(&ba);
pix2.save(&buf, "PNG");
pix1.loadFromData(ba);

In this block, pix1 loaded the byte datas from pix2 after it had setted by labelPix1. Obviously labelPix2 shows the image "test2.png", but it's strange that labelPix1 also shows the image "test2.png" (they show the same image).

Additionally, we introduce the 3rd QPixmap object pix3 and initial it with "test1.png" as the same as pix1. This time labelPix2 don't set pix1 but set pix3 after pix1 load the byte data from pix2. Just like this:

QPixmap pix1(":/test1.png");    
QPixmap pix2(":/test2.png");
QPixmap pix3(":/test1.png");
ui->labelPix1>setPixmap(pix1);

QByteArray ba;
QBuffer buf(&ba);
pix2.save(&buf, "PNG");
pix1.loadFromData(ba);

ui->labelPix2->setPixmap(pix3);

Oh, labelPix1 and labelPix3 show the same image, "test2.png".

I think there must be some mechanism. But I don't know what it really is. Any body has some idea?

1

There are 1 answers

0
thuga On BEST ANSWER

This is due to implicit sharing. I don't know if it's on purpose or not. But if you look at QPixmap::load, you will notice that it calls QPixmap::detach. This means it won't be operating on the shared data anymore. And the docs say: A pixmap is automatically detached by Qt whenever its contents are about to change..

But now when you look at QPixmap::loadFromData, you will notice it doesn't call QPixmap::detach. Now as I quoted the docs before, QPixmap::detach should be called automatically by Qt whenever its contents are about to change. So why not in this case? That I don't know.