Russian Qt Forum

Qt => Пользовательский интерфейс (GUI) => Тема начата: Alp от Апрель 23, 2010, 17:23



Название: QLabel setPixmap неверно уставливается картинка
Отправлено: Alp от Апрель 23, 2010, 17:23
Сидел на библиотеке версии 4.5 проблем не было. Тут решил перейти на 4.6 (2010.02.1) полезли странные глюки.

Код
C++ (Qt)
   QPixmap pix;
 
   pix.load(":/images/trt_logo.png");
   logo->resize(pix.size());
   logo->setPixmap(pix);
   logo->setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
 
   pix.load(":/images/about.png");
   about->resize(pix.size());
   about->setPixmap(pix);
   about->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
 

В итоге я получаю одну и ту же картинку (которая загружается последней) в первом и втором QLabel.
WTF??? Особенный ВТФ получается с учетом того, что внутри setPixmap конструируется новый QPixmap - копия параметра.


Название: Re: QLabel setPixmap неверно уставливается картинка
Отправлено: Marat(Qt) от Апрель 23, 2010, 17:44
Что тут скажешь - новая логика. Используйте
Код:
QPixmap pix1,pix2;
Может быть это хорошо? pix например глобальный у вас, вы его меняете и тут же в label'е все меняется.
А если вам не понраву такое, то перепишите свой код так:
Код:
    QPixmap pix;
 
    pix.load(":/images/trt_logo.png");
    logo->setPixmap(pix.scaled(pix.size()));
    logo->setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
 
    pix.load(":/images/about.png");
    about->setPixmap(pix.scaled(pix.size()));
    about->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
Должно работать


Название: Re: QLabel setPixmap неверно уставливается картинка
Отправлено: SABROG от Апрель 23, 2010, 17:57
В таком виде всё нормально работает.

Код
C++ (Qt)
Widget::Widget(QWidget *parent) :
   QWidget(parent),
   ui(new Ui::Widget)
{
   ui->setupUi(this);
   QPixmap pix;
   pix = QApplication::style()->standardPixmap(QStyle::SP_BrowserStop);
   ui->label->setPixmap(pix);
   pix = QApplication::style()->standardPixmap(QStyle::SP_BrowserReload);
   ui->label_2->setPixmap(pix);
}
 

QLabel копирует картинку и создает новый QPixmap через new внутри метода setPixmap(). Старую можно грохать, её изменение никак не влияет на содержимое в QLabel.


Название: Re: QLabel setPixmap неверно уставливается картинка
Отправлено: Alp от Апрель 23, 2010, 17:58
Что тут скажешь - новая логика. Используйте
Код:
QPixmap pix1,pix2;
Может быть это хорошо? pix например глобальный у вас, вы его меняете и тут же в label'е все меняется.
А если вам не понраву такое, то перепишите свой код так:
Код:
    QPixmap pix;
 
    pix.load(":/images/trt_logo.png");
    logo->setPixmap(pix.scaled(pix.size()));
    logo->setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
 
    pix.load(":/images/about.png");
    about->setPixmap(pix.scaled(pix.size()));
    about->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
Должно работать

А где в Ассистанте про эту новую логику можно почитать? Это реализация принципа "CopyOnWrite" (если я верно понимаю его)? Проблема решилась несколько изящнее: something->setPixmap(pix.copy()) однако то, что эта новость не отображена в документации (может, конечно, и отображена, но сразу же я её не нашел) настораживает.


Название: Re: QLabel setPixmap неверно уставливается картинка
Отправлено: Marat(Qt) от Апрель 23, 2010, 18:03
А где в Ассистанте про эту новую логику можно почитать? Это реализация принципа "CopyOnWrite" (если я верно понимаю его)? Проблема решилась несколько изящнее: something->setPixmap(pix.copy()) однако то, что эта новость не отображена в документации (может, конечно, и отображена, но сразу же я её не нашел) настораживает.
именно о таком изяществе я и хотел вам сказать, scaled тоже создает копию, просто я невнимательно читал ваш код, не понял что label подгоняется под картинку.
Возможно такие новшества описаны в changelog'ах или в release notes'ах. Я сам на подобное попадал(с relationalTableModel).
Цитировать
QLabel копирует картинку и создает новый QPixmap через new внутри метода setPixmap(). Старую можно грохать, её изменение никак не влияет на содержимое в QLabel.
А что если нет?
[IMHO]
Ваш пример мало о чем говорит. Метод load меняет одно(несколько) свойство объекта, а вот метод operator= работает несколько иначе, он возвращает ссылку на QPixmap, т.е. во втором setPixmap вы передаете уже несколько иную ссылку, тогда как в примере топикстартера ссылка одна и та же.
[/IMHO]


Название: Re: QLabel setPixmap неверно уставливается картинка
Отправлено: SABROG от Апрель 23, 2010, 18:24
Какой-то косяк скрылся в методах QPixmap::load, QPixmap::loadFromData.

удалось воспроизвести таким образом:

Код
C++ (Qt)
Widget::Widget(QWidget *parent) :
   QWidget(parent),
   ui(new Ui::Widget)
{
   ui->setupUi(this);
   QPixmap pix;
   QPixmap temp;
 
   temp = QApplication::style()->standardPixmap(QStyle::SP_BrowserReload);
 
   pix = QApplication::style()->standardPixmap(QStyle::SP_BrowserStop);
   ui->label->setPixmap(pix);
 
   QByteArray bytes;
   QBuffer buffer(&bytes);
   buffer.open(QIODevice::WriteOnly);
   temp.save(&buffer, "PNG");
 
   pix.loadFromData(bytes, "PNG");
 
   ui->label_2->setPixmap(pix);
}
 

Вероятно где-то засбоила copy-on-write. Получается QPixmap не считает за write загрузку картинки через load/loadFromData.

Можно подсобить конечно таким образом:

Код
C++ (Qt)
// вставить перед load
pix.fill(Qt::transparent);
 

Тогда copy-on-write срабатывает нормально.


Название: Re: QLabel setPixmap неверно уставливается картинка
Отправлено: SABROG от Апрель 23, 2010, 19:11
Вот он багрепорт, всё уже украдено до нас: http://bugreports.qt.nokia.com/browse/QTBUG-8606

Аж (http://bugreports.qt.nokia.com/images/icons/priority_critical.gif)P1: Critical

Ждите 4.6.3.

Хотел запостить этот код в качестве багрепорта, но раз уж он уже не нужен, оставлю тут для тех, кто захочет проверить, если будет регрессия или подозрения на этот баг:

Код
C++ (Qt)
#include <QtCore/QBuffer>
 
#include <QtGui/QApplication>
#include <QtGui/QGridLayout>
#include <QtGui/QStyle>
#include <QtGui/QPixmap>
#include <QtGui/QLabel>
 
int main(int argc, char* argv[])
{
   QApplication a(argc, argv);
   QWidget mainWidget;
   QGridLayout layout(&mainWidget);
   QLabel label1(&mainWidget);
   QLabel label2(&mainWidget);
 
   layout.addWidget(&label1, 1, 1);
   layout.addWidget(&label2, 1, 2);
   QPixmap pix;
   QPixmap temp;
 
   temp = QApplication::style()->standardPixmap(QStyle::SP_BrowserReload);
   pix = QApplication::style()->standardPixmap(QStyle::SP_BrowserStop);
 
   label1.setPixmap(pix);
 
   QByteArray bytes;
   QBuffer buffer(&bytes);
   buffer.open(QIODevice::WriteOnly);
   temp.save(&buffer, "PNG");
 
#if 0 // set 1 for fix
   pix.fill(Qt::transparent);
#endif
 
   pix.loadFromData(bytes, "PNG");
   label2.setPixmap(pix);
 
   mainWidget.show();
 
   return a.exec();
}
 
 

Для версии Qt 4.6.3 уже 320 (http://bugreports.qt.nokia.com/browse/QTBUG/fixforversion/11572) багфиксов набралось. Один из которых даже мой (http://bugreports.qt.nokia.com/browse/QTBUG-7843) багрепорт.