Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: QPaintEvent, installEventFilter, QPainter, Overpainting
Форум на CrossPlatform.RU > Библиотеки > Qt > Qt Система рисования. Печать
Страницы: 1, 2, 3
Litkevich Yuriy
а есть ещё такая штука как двойная буферизация, её можно запрещать.
igor_bogomolov
Цитата(Litkevich Yuriy @ 27.5.2009, 18:49) *
а есть ещё такая штука как двойная буферизация, её можно запрещать.
Лучше этого не делать. Я уже пробовал. Во первых нам это ничем не помогает, во вторых при ресайзе предыдущее отображение на затирается
SABROG
Цитата(Litkevich Yuriy @ 27.5.2009, 18:49) *
а есть ещё такая штука как двойная буферизация, её можно запрещать.

Установка флагов Qt::WA_PaintOnScreen или Qt::WA_PaintOnScreen для детей приводит к крашу, также как и w->setAutoFillBackground(false);
---
Пардон, это я забыл одно место раскомментировать. В общем всё равно флаги ничем не помогли, autoFillBackground(false) сделал у QListWidget'a фон списка не белым, а как у основного окна.
igor_bogomolov
SABROG, да объясни же, чем не устраивает полученное решение
SABROG
Цитата(igor_bogomolov @ 27.5.2009, 19:02) *
SABROG, да объясни же, чем не устраивает полученное решение

Ну вот если рисовать QPixmap, он же по идее будет рисоваться медленней с ростом количества окон, да и на скрине почему-то в некоторых местах у тебя синяя рамка перекрывает красные линии. К тому же как я уже говорил тут возникает проблема с прозрачностью. Прозрачный фон у виджетов накладывается друг на друга и в итоге я получаю совсем другой цвет. Да и сама по себе проблема до конца не решена.
igor_bogomolov
Цитата(SABROG @ 27.5.2009, 19:11) *
на скрине почему-то в некоторых местах у тебя синяя рамка перекрывает красные линии
В моем примере фильтр устоновлен для textedit->viewport(), для самого textedit - не установлен. Если восползоваться твоей функцией childsRecursive, все будет рисоваться нормально.
Цитата(SABROG @ 27.5.2009, 19:11) *
проблема с прозрачностью
Эт я не проверял. Надо будет посмотреть.
Цитата(SABROG @ 27.5.2009, 19:11) *
Да и сама по себе проблема до конца не решена.
Поподробнее. Что не решено.

Для чего понадобилось рисовать поверх виджетов? Только для этого
SABROG
Много чего придумать можно. Тот же эффект падающего снега. Разные спец.эффекты.

Похоже уже есть смысл копать в сторону backingstore и paintEngine.
igor_bogomolov
Цитата(SABROG @ 27.5.2009, 15:56) *
это альфа-канал, который ставится каждому чайлду. Но из-за того, что прозрачные бэкграунды наслаиваются друг на друга местами альфа-канал суммируется и происходит лажа.
Назнач для кождого такого виджета, с которым лажа происходит, свойство setAutoFillBackground(true). Лажа пропадет :)
SABROG
Ладно, чтобы завершить тему, можешь выложить пример, где бы поверх чайлдов рисовалась картинка с альфа-каналом?

А то я уже устал, если честно.
igor_bogomolov
Цитата(SABROG @ 27.5.2009, 22:12) *
Ладно, чтобы завершить тему, можешь выложить пример, где бы поверх чайлдов рисовалась картинка с альфа-каналом?
Могу конечно. Подчищу проек немного от экспериментов, выложу.


Цитата(SABROG @ 27.5.2009, 22:12) *
А то я уже устал, если честно.
Это твоя тема, тебе решать. Я лишь помочь пытался, в силу своих возможностей.

Transparent Backgrounds in Qt 4.1
SABROG
Меня не столько исходники интересуют, сколько скриншот с результатом :)
igor_bogomolov
Цитата(SABROG @ 27.5.2009, 23:05) *
Меня не столько исходники интересуют, сколько скриншот с результатом
??? Какой от него толк, от скриншота?

Исходники прилагаю, скриншот есть. Картинку сам поменяешь, если что. У меня их просто нет.
Litkevich Yuriy
Вот для эфекта затемнения я бы просто палитру окошка менял перед паказом диалога. И альфа канал бы не использовал, за ненадобностью. Т.к. само окошко все равно не прозрачное.
SABROG
Цитата(Litkevich Yuriy @ 28.5.2009, 5:18) *
Вот для эфекта затемнения я бы просто палитру окошка менял перед паказом диалога. И альфа канал бы не использовал, за ненадобностью. Т.к. само окошко все равно не прозрачное.


Я думал над этим, но это не решение, а обход реальной задачи.

igor_bogomolov, думаю я теперь созрел, чтобы принять этот вариант как окончательный на данный момент. Можно начать писать статью в wiki. Осталось лишь подумать еще над возможностью добавить прозрачную анимацию.
igor_bogomolov
Цитата(SABROG @ 28.5.2009, 9:23) *
Осталось лишь подумать еще над возможностью добавить прозрачную анимацию.
Я вчера ночью, перед тем как выложить пример, немного поэксперементировал. Как раз таки хотел сделать сюрприз и выложить демку с эфектом падающего снега. Сделал 5 прозрачных пнг-шег с хаотично расположенными снижинками. По таймеру - перерисовывал эти картинки, вызывая update() для окна. Оказалось, что таким образом перерисовываются только те виджеты у которых свойство setAutoFillBackground(false). Виджеты с установленным свойством в true, почему то перерисовку игнорируют.
Так что у меня вопрос - чем отличаются события перерисовки через update() и от тех событий которые происходят при ресайзе?
Litkevich Yuriy
Цитата(igor_bogomolov @ 28.5.2009, 12:40) *
чем отличаются события перерисовки через update() и от тех событий которые происходят при ресайзе?
на память: update() - групирует события поэтому его рекомендуют использовать для повышения производительности. Т.е. пачка из нескольких событий рисования будет превращена в одно.

Цитата
void QWidget::update () [slot]
...
This function does not cause an immediate repaint; instead it schedules a paint event for processing when Qt returns to the main event loop. This permits Qt to optimize for more speed and less flicker than a call to repaint() does.

Calling update() several times normally results in just one paintEvent() call.
тык
Цитата
void QWidget::repaint () [slot]

Repaints the widget directly by calling paintEvent() immediately, unless updates are disabled or the widget is hidden.

We suggest only using repaint() if you need an immediate repaint, for example during animation. In almost all circumstances update() is better, as it permits Qt to optimize for speed and minimize flicker.

Warning: If you call repaint() in a function which may itself be called from paintEvent(), you may get infinite recursion. The update() function never causes recursion.
тык

на память немного промазал, групируются не события, а вызовы update()
igor_bogomolov
Все поправил. Теперь и анимация работает нормально.
Прилагаю изменёный проектик. В нем по таймеру перерисовываются звездочки. Получается как анимация. При нажатии на кнопку рисуется затемненный прозрачный фон.

SABROG
, у меня на работе нет возможности сделать гифку, если нетрудно, скомпилируй проектик, засними, и размести здесь. Что бы вроде как итог подвести. Ну и теперь на самом деле можешь писать статью :rolleyes:
SABROG


Написал в wiki как смог, если есть желающие добавить или поправить - милости прошу.
SABROG
wasyota мне дал любопытную ссылочку http://www.qtcentre.org/forum/f-qt-program...lter-12287.html
igor_bogomolov
Цитата(SABROG @ 28.5.2009, 13:52) *
wasyota мне дал любопытную ссылочку http://www.qtcentre.org/forum/f-qt-program...lter-12287.html
Я еще с утра это посмотрел. Что толку. В Qt PostEventFilter пока нет. Но реализацию было бы все равно интересно посмотреть. Приатач сюда posteventfilter.h, а то неохото региться там только из-за этого
SABROG
#ifndef __POSTEVENTFILTER_H
#define __POSTEVENTFILTER_H

#include <QList>
#include <QEvent>

#define WW_POSTEVENTFILTER(superclass) \
public: \
void installPostEventFilter(QObject *monitor){ \
  postFilters.push_front(monitor); \
} \
void removePostEventFilter(QObject *monitor){ \
  postFilters.removeAll(monitor); \
} \
private: \
QList<QObject*> postFilters; \
protected: \
  bool event(QEvent *e){ \
    bool ret = superclass::event(e); \
    if(!ret) \
      return false; \
    foreach(QObject *o, postFilters){ \
    bool r; \
    QMetaObject::invokeMethod(o, "postEventFilter", Qt::DirectConnection, Q_RETURN_ARG(bool, r), Q_ARG(QObject*, this), Q_ARG(QEvent*, e)); \
    if(r) return true; \
    } \
    return true; \
  }

#endif
igor_bogomolov
Цитата(SABROG @ 28.5.2009, 12:20) *
Написал в wiki как смог, если есть желающие добавить или поправить - милости прошу.
Хорошая статья получилась. Не зря мучились почти три дня.

Еще бы ссылочку на эту дему добавить, если вдруг кто то захочет задать вопросс.
Litkevich Yuriy
SABROG, а что если теперь запустить ссылкой в qt-apps?
(через гугл переводчик)
SABROG
Цитата(Litkevich Yuriy @ 28.5.2009, 14:51) *
SABROG, а что если теперь запустить ссылкой в qt-apps?
(через гугл переводчик)

Поподробней отсюда, я ничего не понял :)
Litkevich Yuriy
ну на qt-apps, кто-то утверждал, что задачка не для Qt. Если я ничего не перепутал.
Дак вот дать им ссылку на нашу вики, типа вот как всё это можно сделать.
Дать ссылку на оригинал и на гугловский перевод, чтоб по аглицки могли почитать.
igor_bogomolov
How to sendEvent QPaintEvent ?
SABROG
Цитата(igor_bogomolov @ 28.5.2009, 15:24) *


:) не совсем эта тема, она просто стала продолжением этой: http://www.qtcentre.org/forum/f-qt-program...ilds-21153.html

Щас обновлю все-таки последнюю тему, добавлю туда ссылочку.
Litkevich Yuriy
Ах, да qtcentre.org, конечно, а не qt-apps
SABROG
Вопрос. А ведь QRubberBand тоже рисуется поверх виджетов?
---
Вопрос отпал, это тот самый прослойчатый виджет:

    setAttribute(Qt::WA_TransparentForMouseEvents);
#ifndef Q_WS_WIN
    setAttribute(Qt::WA_NoSystemBackground);
#endif //Q_WS_WIN
    setAttribute(Qt::WA_WState_ExplicitShowHide);

---
Отличие PostEventFilter'а от нашего метода в том, что там переопределяется метод event() вместо installEventFilter'a, ну и соответственно вызывается сначала оригинальный обработчик, а после него вызывается метод postEventFilter. Хуже он тем, что работает только на одном виджете и соответственно каждый такой виджет надо наследовать.
igor_bogomolov
Цитата(SABROG @ 28.5.2009, 17:44) *
Хуже он тем, что работает только на одном виджете и соответственно каждый такой виджет надо наследовать.
Такой метод нам явно не подходит. Наш метод однозначно лучше. Твою статью можно смело в QQ размещать :D


--------------------------------------------------------------------------------
Наконец то научился работать с гиф анимацией через Qt, не воспроизводя ее в QLabel.
Litkevich Yuriy
igor_bogomolov, Прикольно получилось
ViGOur
Цитата(igor_bogomolov @ 28.5.2009, 19:17) *
Твою статью можно смело в QQ размещать
Угу, только думаю нужно грамотно перевести на английский и заслать им. :)
Kagami
igor_bogomolov, выложи, пожалуйста, исходники с мужиком :)
igor_bogomolov
Цитата(Kagami)
igor_bogomolov, выложи, пожалуйста, исходники с мужиком

Выкладываю. Правда координаты где мужика рисую я жестко задавал. Цель была разобраться как работать с гиф анимацией, т.е. считывать кадр из гифки.
ViGOur
igor_bogomolov, выложил твоего мужика на сайт: http://www.crossplatform.ru/node/887. Скорее всего не только Kagami будет интересно посмотреть.

Как зайдешь на сайт, смогу тебе сделать автором данного исходника, чтобы мог поправить или добавить описание. Просто как я понял ты туда ниразу не заходил, по крайней мере залогиненым на форуме. :)
igor_bogomolov
Цитата(ViGOur @ 29.5.2009, 8:56) *
Просто как я понял ты туда ниразу не заходил, по крайней мере залогиненым на форуме.
Так это же главная страница сайта. Всегда на форум захожу через неё. А регистрация по всему ресурсу автоматическая. Сегодня при входе был приятно удивлён, увидев там знакомого мужика.

"Работа с гиф анимацией" - на данный момент звучит очень громко. Там десяти строк не наберется. За все отвечает класс QImageReader, с которым я до конца так и не разобрамся. По данному вопросу я новую тему создам чуть позже.

Предлогаю переименовать "Работа с гиф анимацией". Там всетаки вся прелесть не в работе с гиф, а в самом методе рисования. SABROG использовал термин overpainting. Может стоит его придерживаться?
Litkevich Yuriy
Цитата(igor_bogomolov @ 29.5.2009, 13:13) *
SABROG использовал термин overpainting. Может стоит его придерживаться?
может мы его по-русски запишим? Подберём подходящий вариант.
ViGOur
Это я сам дурак, ограничение в запросе стояло, потому тебя и не нашел.

Сделал тебя автором статьи-исходника, так что можешь поправить как хочешь. :)
ViGOur
Блин, вот думаю исходник SUBROG'a выкладывать на сайте или нет? В принципе есть статья в вики.
Просто он также интересен и полезен! :)
igor_bogomolov
Цитата(ViGOur @ 29.5.2009, 8:56) *
igor_bogomolov, выложил твоего мужика на сайт
Цитата(ViGOur @ 29.5.2009, 20:49) *
Блин, вот думаю исходник SUBROG'a выкладывать на сайте или нет?
Это один и тот же код :) Анимация только разная. В первом звездочки, во втором "мужик". Поэтому я и предлогал переименовать.
Цитата(igor_bogomolov)
Там всетаки вся прелесть не в работе с гиф, а в самом методе рисования.
ViGOur
Цитата(igor_bogomolov @ 29.5.2009, 23:31) *
Поэтому я и предлогал переименовать.
Вроде как ты автор того исходника, так что дерзай, если есть идеи. :)
Litkevich Yuriy
Цитата(kwisp @ 30.5.2009, 14:42) *
может вообще не стоит русский аналог искать а писать просто по русски оверрисование.
стОит. Надо подумать, здесь
SABROG
Не должно muzhik'у быть одному, поэтому я склепал ему бабу.



Решил попробовать схожий метод перехвата эвентов, но уже в глобальном виде - через переопределение QApplication::notify(). Принцип почти такой же за исключением того, что здесь не нужно использовать installEventFilter и рекурсию по детям.

bool MyApplication::notify(QObject *receiver, QEvent *event)
{
    if (QEvent::Paint == event->type() && m_overWidget) {
        bool ret = QApplication::notify(receiver, event);
        QWidget *widget = qobject_cast<QWidget *>(receiver);
        if (!m_overWidget->isAncestorOf(widget))
            return ret;
        QPainter painter(widget);

        QWidget *parent = widget;

        while(parent && parent->parentWidget() && (parent->parentWidget() != m_overWidget))
            parent = parent->parentWidget();

        if (parent != m_overWidget) {
            QPoint point = widget->mapTo(parent, parent->pos());
            QRect rect = widget->rect().translated(point);

            painter.setWindow(rect);
        }

        painter.drawPixmap(m_pix.rect(), m_pix);
        return ret;
    }
    return QApplication::notify(receiver, event);
}


В примере используется .mng анимация с классом QMovie. Есть баги, требующие доработки.

Исходники.
SABROG
Это тролли так шутят или они действительно планируют все-таки реализовать подобный функционал в Qt 5.0.0?

http://bugreports.qt.nokia.com/browse/QTBUG-1615
Litkevich Yuriy
Ну, а почему бы в 5-ке этому не появится (пострисованию)
SABROG
Цитата(Litkevich Yuriy @ 31.10.2009, 0:36) *
Ну, а почему бы в 5-ке этому не появится (пострисованию)


Ну если Qt 4.3.0 вышла в 2007 году, то 5.0.0 выйдет наверно, когда мы будем уже дедушками.
BRE
Цитата(SABROG @ 30.10.2009, 23:46) *
Ну если Qt 4.3.0 вышла в 2007 году, то 5.0.0 выйдет наверно, когда мы будем уже дедушками.

IMHO, сейчас релизы чаще выходят. Думаю год два.... :)
Litkevich Yuriy
Цитата(BRE @ 31.10.2009, 2:50) *
Думаю год два....
да быстрее и не надо, а то там каки будут.
Да и судя по странице проекта Qt в разделе версии целая куча всего, что отложено на "после 5-ки"
Цитата
4.5.2 1
4.5.3 11
4.5.4 (Next Patch Release) 44
4.6.0 (Next Minor Release) 424
4.6.1 (Next Patch Release) 1
4.6.x 67
4.7.x 10
5.0.0 (Next Major Release) 80
Some future release

Стало быть 5-ки слишком долго ждать не прийдётся. Одно интересно ВинХП похоронят в 5-ке или нет
Litkevich Yuriy
Тему разделил: Ализе́ Жакоте
Litkevich Yuriy
Может будет интересно: тык
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Форум IP.Board © 2001-2024 IPS, Inc.