crossplatform.ru

Здравствуйте, гость ( Вход | Регистрация )

2 страниц V   1 2 >  
Ответить в данную темуНачать новую тему
> Как рисовать на QImage с прозрачностью?
Rocky
  опции профиля:
сообщение 4.2.2010, 19:43
Сообщение #1


Старейший участник
****

Группа: Участник
Сообщений: 530
Регистрация: 22.12.2008
Из: Санкт-Петербург
Пользователь №: 463

Спасибо сказали: 22 раз(а)




Репутация:   7  


Всем привет!
вот тут http://www.forum.crossplatform.ru/index.php?showtopic=4154 Litkevich Yuriy выложил пример AeroButton. В программе сделал кнопки примерно также. Но чтука в том что под виндой эти кнопки получаются с идеально на мой взгляд ровными обводами засчет антиалайзинга.. А вот под линуксом они ужасны. Вычитал, что в иксах нужно для достижения такого же результат включить какую-то опцию отрисовки. Но есть универсальный способ: рисование на QImage (т.е. как бы использование его движка, а не "движка" ОС). Вот делаю как в книге написано =)

void CRoundButton::paintEvent(QPaintEvent *pEvent)
{
    

    QImage oImage(this->size(), QImage::Format_ARGB32_Premultiplied);
    QPainter oImagePainter(&oImage);
    oImagePainter.initFrom(this);
    oImagePainter.setRenderHint(QPainter::Antialiasing, true);
    oImagePainter.eraseRect(this->rect());
//тут отрисовка по сути таже что и в примере aerobutton (только на oImagePainter)
//и потом
    oImagePainter.end();

    QPainter oWidgetPainter(this);
    oWidgetPainter.drawImage(0, 0, oImage);


Кнопки рисуются, причем прозрачные... но вот по краям виден белый прямоугольный фон. Вот пример:



Как это можно победить? Пробовал играться с QPainter::CompositionMode, максимально только к этому беломы фону прозрачность добавляется....но сам он не исчезает естественно...

Спасибо!
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 4.2.2010, 21:15
Сообщение #2


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9669
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

Спасибо сказали: 807 раз(а)




Репутация:   94  


Rocky, а ты про painter.setOpacity не забыл?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Rocky
  опции профиля:
сообщение 4.2.2010, 21:28
Сообщение #3


Старейший участник
****

Группа: Участник
Сообщений: 530
Регистрация: 22.12.2008
Из: Санкт-Петербург
Пользователь №: 463

Спасибо сказали: 22 раз(а)




Репутация:   7  


неа (( в том-то и дело что не забыл
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 4.2.2010, 21:30
Сообщение #4


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9669
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

Спасибо сказали: 807 раз(а)




Репутация:   94  


Rocky, ты можешь выложить код AeroButton модифицированный под QImage?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Rocky
  опции профиля:
сообщение 4.2.2010, 21:39
Сообщение #5


Старейший участник
****

Группа: Участник
Сообщений: 530
Регистрация: 22.12.2008
Из: Санкт-Петербург
Пользователь №: 463

Спасибо сказали: 22 раз(а)




Репутация:   7  


Вот:
Раскрывающийся текст
void CRoundButton::paintEvent(QPaintEvent *pEvent)
{
    Q_UNUSED(pEvent);

    QImage oImage(this->size(), QImage::Format_ARGB32_Premultiplied);
    QPainter oImagePainter(&oImage);
    //oImagePainter.setCompositionMode(QPainter::CompositionMode_Xor); //это самое лучшее - белый фон почти невидим, но он есть
    oImagePainter.initFrom(this);
    oImagePainter.setRenderHint(QPainter::Antialiasing, true);
    oImagePainter.eraseRect(this->rect());

    //test for state changes
    QColor button_color;
    if (this->isEnabled())
    {
        m_bHovered ? button_color = m_oHighlight : button_color = m_oColor;
        if (m_bPressed) button_color = m_oPress;
    }
    else
    {
        button_color = QColor(50, 50, 50);
    }

    QRect button_rect = this->geometry();

    //outline
    oImagePainter.setPen(QPen(QBrush(Qt::black), 2.0));
    QPainterPath outline;
    outline.addRoundRect(0, 0, button_rect.width(), button_rect.height(), m_nRoundness, m_nRoundness);
    oImagePainter.setOpacity(m_dOpacity);
    oImagePainter.drawPath(outline);

    //Linear Gradient
    QLinearGradient oLinearGradient(0, 0, 0, button_rect.height());
    oLinearGradient.setSpread(QGradient::ReflectSpread);
    oLinearGradient.setColorAt(0.0, button_color);
    oLinearGradient.setColorAt(0.4, m_oShadow);
    oLinearGradient.setColorAt(0.6, m_oShadow);
    oLinearGradient.setColorAt(1.0, button_color);

    QBrush brush(oLinearGradient);
    oImagePainter.setBrush(brush);
    oImagePainter.setPen(QPen(QBrush(button_color), 2.0));

    //main button
    QPainterPath oImagePainter_path;
    oImagePainter_path.addRoundRect(1, 1, button_rect.width() - 2, button_rect.height() - 2, m_nRoundness, m_nRoundness);
    oImagePainter.setClipPath(oImagePainter_path);

    oImagePainter.setOpacity(m_dOpacity);
    oImagePainter.drawRoundRect(1, 1, button_rect.width() - 2, button_rect.height() - 2, m_nRoundness, m_nRoundness);

    //glass highlight
    oImagePainter.setBrush(QBrush(Qt::white));
    oImagePainter.setPen(QPen(QBrush(Qt::white), 0.01));
    oImagePainter.setOpacity(0.30);
    oImagePainter.drawRect(1, 1, button_rect.width() - 2, (button_rect.height() / 2) - 2);

    //text
    QString sText = this->text();
    if(!sText.isNull())
    {
        QFont font = this->font();
        oImagePainter.setFont(font);
        oImagePainter.setPen(Qt::white);
        oImagePainter.setOpacity(1.0);
        oImagePainter.drawText(0, 0, button_rect.width(), button_rect.height(), Qt::AlignCenter, sText);
    }

    oImagePainter.end();

    QPainter oWidgetPainter(this);
    //oWidgetPainter.setOpacity(m_dOpacity);//без разницы что включен, что нет
    oWidgetPainter.drawImage(0, 0, oImage);

    pEvent->accept();
}
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 4.2.2010, 23:02
Сообщение #6


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9669
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

Спасибо сказали: 807 раз(а)




Репутация:   94  


Rocky, сделал попроще чем у тебя и всё работает (Проверял на виндовозе). Проверь
Прикрепленный файл  AeroButton2.zip ( 4,44 килобайт ) Кол-во скачиваний: 452

П.С. на окно добавил переключатель, чтобы рисовать напрямую или через QImage
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Rocky
  опции профиля:
сообщение 4.2.2010, 23:57
Сообщение #7


Старейший участник
****

Группа: Участник
Сообщений: 530
Регистрация: 22.12.2008
Из: Санкт-Петербург
Пользователь №: 463

Спасибо сказали: 22 раз(а)




Репутация:   7  


Странно.. но действительно работает.. ))

дело было в fill(...)

=)

Сообщение отредактировал Rocky - 5.2.2010, 0:06
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 5.2.2010, 0:22
Сообщение #8


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9669
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

Спасибо сказали: 807 раз(а)




Репутация:   94  


Rocky, отпишись, на Линухе использование QImage даёт лучшее сглаживание или нет.
Ну и если будешь продолжать использовать QImage, то лучше рисовать на QImage в отдельном методе, который вызывается в конструкторе и в методах установки свойств. А в обработчике события рисования только выводить уже готовый QImage (QPainter::drawImage()). Так будет быстрее отрисовка происходить
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Rocky
  опции профиля:
сообщение 5.2.2010, 0:50
Сообщение #9


Старейший участник
****

Группа: Участник
Сообщений: 530
Регистрация: 22.12.2008
Из: Санкт-Петербург
Пользователь №: 463

Спасибо сказали: 22 раз(а)




Репутация:   7  


Да, насчет отрисовки завтра переделаю... Весь день буду оптимизацией заниматься... Хотя стоп... Litkevich Yuriy можно задам вопрос, который давно меня мучает... Вроде как он касается этого. Если в конструкторе класса формировать пусть тот же QImage, то как? В смысле если мы находимся внутри самого конструктора класса, то его объект еще не создан. И тем более не отображен на экране. Как тогда получить правильные размеры всех виджетов и пр? Я щас так делаю: просто в main-е после того, как вызвал exec(...) или show(...) главного окна, вызываю некий метод Initialize(...) который по сути далее вызывается иерархически по вссем потомкам главного виджета (окна).. Но как-то не очень нравится этот способ... Может можно как-то лучше?



Вобщем щас вот так в линуксе выглядит:

Завтра на работе сделаю скрин как с этим же кодом в XP.

---------------------------------------
Вот так выглядит картинка в винде


Сообщение отредактировал Rocky - 5.2.2010, 9:02
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 5.2.2010, 4:30
Сообщение #10


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9669
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

Спасибо сказали: 807 раз(а)




Репутация:   94  


Цитата(Rocky @ 5.2.2010, 3:50) *
Если в конструкторе класса формировать пусть тот же QImage, то как? В смысле если мы находимся внутри самого конструктора класса, то его объект еще не создан. И тем более не отображен на экране. Как тогда получить правильные размеры всех виджетов и пр?
есть разные способы применительно к твоей задаче:
1) Поискать по форуму по поводу определения размеров в конструкторе (точно помню обсуждалось)
2) Отлавливать resizeEvent и корректировать QImage
3) Сделать как в файле примера %QTDIR%\examples\painting\svgviewer\svgview.cpp класс SvgRasterView
4) переопределить метод show(), в котором вызывать метод базового класса (после него станут известны размеры), а затем корректировать QImage
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение

2 страниц V   1 2 >
Быстрый ответОтветить в данную темуНачать новую тему
Теги
Нет тегов для показа


6 чел. читают эту тему (гостей: 6, скрытых пользователей: 0)
Пользователей: 0




RSS Текстовая версия Сейчас: 25.11.2024, 7:43