crossplatform.ru

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

 
Ответить в данную темуНачать новую тему
> проблемы с QWidget::setMask
Rocky
  опции профиля:
сообщение 8.4.2010, 22:45
Сообщение #1


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

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

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




Репутация:   7  


Всем привет! Помогите пожалуйста разобраться с проблемкой. В программе нужно сделать определенную анимацию. И требуется, чтобы эта анимация как бы пробегала по основной программе (вот как пример это всякие зверушки/девушки/помощники на рабочем столе). У меня бегающий дядя )). Я сделал виджет, в котором переопределил paintEvent. Далее задал этому виджету последовательность картинок *.png (с прозрачностью) и в таймере меняю счетчик кадров картинок (т.к. мужик бежит), затем вызываю метод repaint(). В самом обработчике paintEvent() я вызываю clearMask и затем setMask и после этого рисую новый кадр. В виндовсе вроде как нареканий нет никаких... только разве что медленно отрисовывает (виджет не успевает обрезаться по маске - ну это терпимо)... А в линуксе большие траблы ( При каждой перерисовке у меня мигает черный прямоугольник размером с весь виджет.. и из-за чего он возникает и как его убрать непонятно (. Помогите советом, как можно решить проблему? Может забабахать все картинки в какой-нить gif? Но как его отображать с учетом прозрачности тогда? маска ведь своя для каждого кадра... Или есть еще какие-нить анимированные форматы такие, в которые можно было бы без проблем перегнать png и qt бы их поддерживал?

Спасибо!

PS. Вот кусок кода как я делаю.
void CMovie::SetPictureSequence(const std::vector<QImage>& roImages)
{
    m_roImages = roImages;
    m_nFramesCount = m_roImages.size();

    for (std::vector<QImage>::const_iterator itImage = m_roImages.begin(); itImage != m_roImages.end(); ++itImage)
    {
        m_roImageMasks.push_back(QPixmap::fromImage(*itImage).mask());
    }
}
void CMovie::paintEvent(QPaintEvent *pEvent)
{
    Q_UNUSED(pEvent);

    QPainter oWidgetPainter(this);

    if (m_nCurrentFrame < 0 || m_nCurrentFrame >= m_nFramesCount) return;
    
    //рисуем картинку
    if (!m_roImages.at(m_nCurrentFrame).isNull())
    {
        this->clearMask();
        this->setMask(m_roImageMasks.at(m_nCurrentFrame));
        oWidgetPainter.drawImage(0, 0, m_roImages.at(m_nCurrentFrame));
    }
}
void CMovie::OnTimer()
{
    if (m_nCurrentFrame == m_nFramesCount - 1)
    {
        m_nCurrentFrame = 0;
        emit movieFinished();
    }
    else ++m_nCurrentFrame;
    
    this->repaint();
}


Сигнал movieFinished соединен со слотом начала анимации (останов таймера у которого слот OnTimer, установка счетчика на 1-й кадр, запуск таймера)
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
igor_bogomolov
  опции профиля:
сообщение 8.4.2010, 22:58
Сообщение #2


Профессионал
*****

Группа: Сомодератор
Сообщений: 1215
Регистрация: 22.3.2009
Из: Саратов
Пользователь №: 630

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




Репутация:   29  


Цитата(Rocky @ 8.4.2010, 23:45) *
Может забабахать все картинки в какой-нить gif? Но как его отображать с учетом прозрачности тогда? маска ведь своя для каждого кадра...
Я когда то делал такой эксперимент с gif-ом. Там ты найдешь как это делается с использованием гиф-анимации.
Но самое печальное, что тот пример работает тоже только под Windows. Что мешает работать под Linux не знаю, не разбирался. Может в выходные попробую ещё по экспериментировать.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Rocky
  опции профиля:
сообщение 8.4.2010, 23:13
Сообщение #3


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

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

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




Репутация:   7  


Да, я уже читал, пасиб) Щас более внимательно еще раз посмотрю. Жаль что в линуксе не работает... как раз именно он и нужен =(
Тут где-то еще пример был как рисовать поверх всех, так там была тетка танцующая... файл *.mng. Может в эту сторону тоже покопать. Тока что это за формат такой.... :search: Полез в википедию...
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Rocky
  опции профиля:
сообщение 12.4.2010, 9:19
Сообщение #4


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

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

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




Репутация:   7  


Чето вообще непонятно ничего =(
Вот тут шла речь о отрисовке изображения поверх виджетов. В частности была написана такая вот функция для отрисовки кадра анимации mng:
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);
}


Если скомпилить пример baba, то каждый кадр анимации рисуется на прозрачном фоне. Как так получается? Никаких setMask ничего такого.... Я пишу так:
CLabel::CLabel(const QString& sFileName, QWidget *parent) : QWidget(parent)
{
    m_pMovie = new QMovie(sFileName, "mng", this);
    QObject::connect(m_pMovie, SIGNAL(frameChanged(int)), this, SLOT(OnFrameChanged(int)));

    m_oPixmap.fill(Qt::transparent);
#ifdef Q_WS_WIN
    this->setWindowFlags(Qt::Window | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint);
#else
    this->setWindowFlags(Qt::Window | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint| Qt::X11BypassWindowManagerHint);
#endif

    m_pMovie->start();
}

void CLabel::OnFrameChanged(int frameNumber)
{
    m_oPixmap = m_pMovie->currentPixmap();
    this->repaint();
}

void CLabel::paintEvent(QPaintEvent *pEvent)
{
    Q_UNUSED(pEvent);

    QPainter oPainter(this);
    oPainter.drawPixmap(m_oPixmap.rect(), m_oPixmap);
}


и нифига.... Все рисуется на каком-то дурацком бело-бежевом квадрате.... Как так? =(

Сообщение отредактировал Rocky - 12.4.2010, 9:20
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 12.4.2010, 9:39
Сообщение #5


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

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

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




Репутация:   94  


может дело в самой картинке? Ты пробовал картинку из "бабы"?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Rocky
  опции профиля:
сообщение 12.4.2010, 9:49
Сообщение #6


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

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

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




Репутация:   7  


Пробовал... я уже думаю может дело вот в этой строке
this->setWindowFlags(Qt::Window | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint);


Думаю как бы проверить.... потому что этот виджет на котором все рисуется должен быть поверх главного окна.... и если флаги не ставить, то его не видно вообще (

UPD
Неа, не похоже что в ней

Сообщение отредактировал Rocky - 12.4.2010, 9:54
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Rocky
  опции профиля:
сообщение 12.4.2010, 11:21
Сообщение #7


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

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

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




Репутация:   7  


Все как-то очень странно...
1. в paintEvent добавил QPainter::setOpacity(...);
2. this->setWindowFlags(Qt::Window | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint); заменил на this->setWindowFlags(this->windowFlags() | Qt::WindowStaysOnTopHint);
3. В качестве parentWidget указал класс, производный от QMainFrame (т.е. самый главный), а не 5-й производный от него...

И вот так все работает... Нифига не понял в чем фишка.. Но факт на лицо =)

ЗЫ. А с gif-ом лучче вообще не заморачиваться. Хотя срок патента на него вроде как истек, но качество у него не супер. Плюсь в qt все-таки он как-то оч непонятно поддерживается. Лучче тогда уж юзать mng - это анимированный png. И качество неплохое, и поддержка есть (тока в линуксе нужно специально компилить еще плагин qmng). Откопал прогу, называется PNG/MNG Construction Set. Оч легкая в освоении.

ЗЗЫ. SABROG, спасибо еще раз за ImageMagic - пока ее искал нашел вот этот "PNG/MNG Construction Set". :)

Сообщение отредактировал Rocky - 12.4.2010, 11:21
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение

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


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




RSS Текстовая версия Сейчас: 30.9.2020, 18:31