Russian Qt Forum
Ноябрь 23, 2024, 13:52 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: [РЕШЕНО] Мерцание при анимации  (Прочитано 6255 раз)
borkk
Гость
« : Апрель 19, 2013, 11:38 »

Добрый день!
Разработал свой класс ArrowWidget (на основе QWidget), состоящий из нескольких стрелок (направленных вверх или вниз). При нажатии на кнопку стрелки должны либо начать анимацию, либо закончить (в зависимости от нажатой кнопки), рисую при помощи QPainter-а, массивом полигонов (QPolygon), анимация реализована при помощи QPropertyAnimation. Обнаружил проблему, если эти стрелочки отрисовывать в виджете QWidget или просто в окне MainWindow, то при анимации мерцает нижняя стрелка, причем мерцание начинается только после повторного нажатия на клавишу анимации. Видео с примером по ссылке http://youtu.be/3gHhM-3yAeA
Решил проблему при помощи Graphics View Framework, создал сцену (QGraphicsScene), вид (QGraphicsView), вид сделал родительским для экземпляра ArrowWidget (экземпляр называется myWidget) и добавил этот экземпляр на сцену. Теперь при нажатии клавиш анимации мерцания не возникает.
Соответственно вопрос, корректно ли решение? Есть ли другие варианты? А то мне кажется, что это как из пушки по воробьям...

ArrowWidget описание класса
Код:
class ArrowWidget : public QWidget
{
    Q_OBJECT
public:
    ArrowWidget(QWidget *parent = 0);
    virtual ~ArrowWidget() {}
    void paintEvent(QPaintEvent *pe);
    bool isDown();
    bool isUp();
    void setDown();
    void setUp();
    void setGoingUp(bool b);
    bool isGoingUp();
    void setGoingDown(bool b);
    bool isGoingDown();

private:
    bool posArrows; // 0 - down; 1 - up
    bool goingUp;
    bool goingDown;
    QPropertyAnimation *animation;
};

ArrowWidget конструктор и методы
Код:
ArrowWidget::ArrowWidget(QWidget *parent) : QWidget(parent)
{
    resize(parent->size());
    posArrows = false;
    animation = new QPropertyAnimation(this, "geometry");
    animation->setDuration(1000);
    animation->setLoopCount(-1);
    animation->setStartValue(QRect(0, 0, this->width(), this->height()));
//    setAutoFillBackground(true);
//    setAttribute(Qt::WA_OpaquePaintEvent,true);
}

void ArrowWidget::paintEvent(QPaintEvent *pe)
{
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing, true);
    painter.setBrush(QBrush(Qt::black));
    painter.setPen(QPen(Qt::black));

    const int arrowsNum = (height()/13);
    QPolygon arrows[arrowsNum];
    if(!posArrows) {
        for(int i = 0; i < arrowsNum; i++) {
            arrows[i] << QPoint(1,(11*i)+2+(i*2)) << QPoint(19,(11*i)+2+(i*2)) << QPoint(10,(11*(i+1))+2+i*2);
            painter.drawPolygon(arrows[i]);
        }
    } else {
        for(int i = 0; i < arrowsNum; i++) {
            arrows[i] << QPoint(1,(11*(i+1))+2+(i*2)) << QPoint(19,(11*(i+1))+2+(i*2)) << QPoint(10,(11*i)+2+i*2);
            painter.drawPolygon(arrows[i]);
        }
    }
}

bool ArrowWidget::isUp()
{
    if(posArrows == true)
        return true;
    else
        return false;
}

void ArrowWidget::setUp()
{
    posArrows = true;
    update();
}

void ArrowWidget::setGoingUp(bool b)
{
    setUp();
    animation->setEndValue(QRect(0, -13, this->width(), this->height()));
    if(b) {
        animation->stop();
        animation->start();
    } else {
        animation->stop();
        update();
    }
}

bool ArrowWidget::isGoingUp()
{
    return goingUp;
}

MainWindow.h
Код:
class MainWindow : public QMainWindow
{
    Q_OBJECT
    
public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
    
private slots:
    void on_pushButton_clicked();
    void on_pushButton_3_clicked();
    void on_pushButton_2_clicked();
    void on_pushButton_4_clicked();

private:
    Ui::MainWindow *ui;
    ArrowWidget *myWidget;
};

MainWindow.cpp
Код:
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    //Если сделать родителем ui->widget, и закомментировать строчки ниже, стрелочки будут мерцать
    myWidget = new ArrowWidget(ui->graphicsView);

    QGraphicsScene *scene = new QGraphicsScene;
    ui->graphicsView->setScene(scene);
    ui->graphicsView->setBackgroundBrush(QColor(240,240,240));

    scene->addWidget(myWidget);

}

архив с проектом во вложении
« Последнее редактирование: Апрель 23, 2013, 13:40 от borkk » Записан
Bepec
Гость
« Ответ #1 : Апрель 19, 2013, 12:03 »

Такое чуйство, что у вас идёт двойная перерисовка или двойной вызов анимации. В результате чего оно и дёргается.

Код не смотрел, нет времени Улыбающийся
Записан
borkk
Гость
« Ответ #2 : Апрель 19, 2013, 12:09 »

при нажатии на клавишу вызывается метод
Код:
animation->stop();
затем
Код:
animation->start();
. Насчет двойной перерисовки не могу знать, где посмотреть? Как будет время, гляньте код, может подскажете чего.
Записан
Bepec
Гость
« Ответ #3 : Апрель 19, 2013, 12:15 »

Возможно в выходные посмотрю. А мб кто нибудь решит раньше.

НЕНАВИЖУ, НЕНАВИЖУ компиляторы, не поддерживающие стандарт Веселый Массив динамической длины... Это ж ппц.
« Последнее редактирование: Апрель 22, 2013, 13:52 от Bepec » Записан
Bepec
Гость
« Ответ #4 : Апрель 22, 2013, 13:58 »

Никаких артефактов наподобие тех, что в вашем видео не обнаружил. спокойно всё ковыляет.
Записан
borkk
Гость
« Ответ #5 : Апрель 23, 2013, 13:09 »

Ага, как только убрал массив динамической длины стало нормально отображаться)
Вот так вот временное становится постоянным и мешает разработке. Спасибо!
Записан
Bepec
Гость
« Ответ #6 : Апрель 23, 2013, 13:24 »

Вы ещё подумайте, если это у вас используется вне сцены, мб стоит просто отрисовывать и не загромождать свои программы ещё и сценами?

PS на каждый элемент по сцене - это ж ппц будет.
Записан
borkk
Гость
« Ответ #7 : Апрель 23, 2013, 13:38 »

Нет, у меня мерцало при анимации без сцены, когда я отрисовывал массив, именно поэтому добавил сцену (см. первый пост, написал, что победил проблему, но кажется, что это как из пушки по воробьям). Сейчас убрал сцены и вид и просто создаю QPolygon и рисую им в цикле
Код:
QPolygon arrows;
   for(int i = 0; i < arrowsNum; i++) {
       arrows.clear();
       arrows << QPoint(1,(11*i)+2+(i*2)) << QPoint(19,(11*i)+2+(i*2)) << QPoint(10,(11*(i+1))+2+i*2);
       painter.drawPolygon(arrows);
   }
Никаких мерцаний при анимации не наблюдаю.
« Последнее редактирование: Апрель 23, 2013, 13:40 от borkk » Записан
Bepec
Гость
« Ответ #8 : Апрель 23, 2013, 13:54 »

Слава богу. Улыбающийся
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.046 секунд. Запросов: 21.