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-й кадр, запуск таймера)
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
 
Начать новую тему
Ответов
Rocky
  опции профиля:
сообщение 12.4.2010, 9:19
Сообщение #2


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

Группа: Участник
Сообщений: 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
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение

Сообщений в этой теме


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


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




RSS Текстовая версия Сейчас: 11.3.2025, 10:23