【问题标题】:Navigate among GIFs with QMovie and signals/slots in Qt C++在 Qt C++ 中使用 QMovie 和信号/插槽在 GIF 之间导航
【发布时间】:2018-02-10 16:03:32
【问题描述】:

我正在使用 Qt QMovie 播放一组 GIF。在到达 GIF 的最后一帧时,我断开信号,停止 QMovie 并开始下一个 QMovie。在这一步之前,代码可以正常工作。

在此之后,我介绍了可以在 GIF 中导航的下一个和上一个按钮。这些按钮的 onClick 动作与上面的动作相同,只是我不等待最后一帧,而是立即断开连接并停止电影。

这会随机导致所有 GIF 的播放速度比正常速度快。而且,即将到来的 GIF 甚至在到达帧结束之前就会突然导航到下一个 gif。

这种效果会以指数方式级联消耗大量内存。最终导致应用崩溃。

这是我的头文件

class AnimationBox : public QWidget
{
    Q_OBJECT

public:
    explicit AnimationBox(QWidget *parent = 0);
    ~AnimationBox();

private slots:
    void loopAnimation(int frame);
    void changeSlide(int direction = 1);
    void prevGIFSlot();
    void nextGIFSlot();

private:
    Ui::AnimationBox *ui;
    std::vector<QMovie*> movieVector;  
    int currentMovieIndex;
};

这是我的 cpp 文件

AnimationBox::AnimationBox(QWidget *parent) 
: QWidget(parent)
, ui(new Ui::AnimationBox),
{
    ui->setupUi(this);

    currentMovieIndex = 0;
    movieVector.push_back(new QMovie("/Users/qq/Desktop/gif1.gif"));
    movieVector.push_back(new QMovie("/Users/qq/Desktop/gif2.gif"));
    movieVector.push_back(new QMovie("/Users/qq/Desktop/gif3.gif"));

    ui->movieLabel->setMovie(movieVector[currentMovieIndex]);
    movieVector[currentMovieIndex]->start();

    connect(movieVector[currentMovieIndex], SIGNAL(frameChanged(int)), this, SLOT(loopAnimation(int)));
    connect(ui->leftButton, SIGNAL(clicked()), this, SLOT(prevGIFSlot()));
    connect(ui->rightButton, SIGNAL(clicked()), this, SLOT(nextGIFSlot()));

}

void AnimationBox::loopAnimation(int frame)
{    
    if (frame == movieVector[currentMovieIndex]->frameCount() - 1)
    {
        disconnect(movieVector[currentMovieIndex], SIGNAL(frameChanged(int)), this, SLOT(loopAnimation(int)));
        movieVector[currentMovieIndex]->stop();
        changeSlide();
    }
}

void AnimationBox::prevGIFSlot()
{
    disconnect(movieVector[currentMovieIndex], SIGNAL(frameChanged(int)), this, SLOT(loopAnimation(int)));
    movieVector[currentMovieIndex]->stop();        
    changeSlide(-1);
}

void AnimationBox::nextGIFSlot()
{
    disconnect(movieVector[currentMovieIndex], SIGNAL(frameChanged(int)), this, SLOT(loopAnimation(int)));
    movieVector[currentMovieIndex]->stop();        
    changeSlide(1);
}

void AnimationBox::changeSlide(int direction)
{
    currentMovieIndex = (currentMovieIndex + direction) % movieVector.size();
    ui->movieLabel->setMovie(movieVector[currentMovieIndex]);
    movieVector[currentMovieIndex]->start();

    connect(movieVector[currentMovieIndex], SIGNAL(frameChanged(int)), this, SLOT(loopAnimation(int)));
}

【问题讨论】:

  • 你在哪里声明了changeSlide()?你在哪里实现了 changeGIF()?
  • 对不起。更正了函数名称。虽然不介意任何语法错误。没有编译错误。我真的很想知道应该如何正确处理对象以及启动、停止和连接的正确使用顺序。

标签: c++ qt animation synchronization


【解决方案1】:

而且,即将到来的 GIF 甚至会突然导航到下一个 gif 在到达帧结束之前。

这是因为插槽 loopAnimation(int frame) 在最后一帧加载后被调用,并且您的插槽停止了电影.. 在帧本身播放之前足够早,所以它被砍掉了.. . 这种细微的变化向您展示了如何避免这种情况:

void AnimationBox::loopAnimation(int frame)
{
    if (frame == 0)
    {
        disconnect(movieVector[currentMovieIndex], SIGNAL(frameChanged(int)), this, SLOT(loopAnimation(int)));
        movieVector[currentMovieIndex]->stop();
        changeSlide();
    }
}

请注意,这是一个条件解决方案,因为您实际上是在连接到插槽之前开始播放电影的......所以它最初在帧为 0 时不会被命中,但它会在下一个动画周期被命中,但是下一个动画在这里停止。如果您更改代码内容.. 这可能不是最佳解决方案.. 但只需确保在停止电影之前播放最后一帧。

这会随机导致所有 GIF 的播放速度比正常速度快。

这是不可重现的!我可以运行您的代码而不会看到此问题...这可能意味着它可能与您的标签 UI 设计..或 GIF 本身中的任何内容有关...如果您有任何设置,请尝试将您的 UI 设置设为默认值我们在代码中没有看到的其他设置。底线:它在这里正常工作。

2 厘米:

  • 最好使用 Qt 新的 Signal/Slot 语法:

    connect(ui-&gt;leftButton, &amp;QPushButton::clicked, this, &amp;AnimationBox::prevGIFSlot);

  • 一个好的方法是放置你的信号/插槽connect()之前你开始对象的逻辑(在你的情况下开始电影),在你的情况下你开始电影..然后..您建立信号/插槽连接..我认为这不是一个好习惯。

【讨论】:

  • 您可能无法通过单击下一个/上一个按钮来重现该问题。不断地点击左键一段时间,右键点击一段时间,混合序列并观察GIF。为了更清楚,把 qDebug() frameCount() - 1
  • @DeCoDeR,没区别~你的操作系统/QT Crtr/Qt Ver是什么
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-08
  • 1970-01-01
相关资源
最近更新 更多