在QT C 中使用QMOVIE和信号/插槽之间在GIF中导航

Navigate among GIFs with QMovie and signals/slots in Qt C++

本文关键字:导航 插槽 之间 信号 GIF QMOVIE QT      更新时间:2023-10-16

我正在使用qt qmovie播放GIF集合。到达GIF的最后一帧后,我断开信号,停止QMOVIE并开始下一个Qmovie。在此步骤之前,代码正常。

之后,我介绍了可以在GIF上导航的下一个和以前的按钮。这些按钮的动作动作与上述动作相同,除非我立即断开并停止电影。

这会随机导致所有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)));
}

以及即将到来的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时,它在下一个动画周期中不会命中0,但是下一个动画在这里停止。如果您更改代码的内容..这可能不是最好的解决方案。

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

这是不可再现的!我可以在不看到此问题的情况下运行您的代码...这可能意味着它可能与您的标签UI设计有关。我们在代码中看不到的其他设置。底线:它通常在这里工作。

2评论:

  • 最好使用QT新信号/插槽语法:

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

  • 一种很好的方法是将信号/插槽connect() 放在之前启动对象的逻辑(在您的情况下开始电影(,如果您开始电影。然后..您建立信号/插槽连接..我相信这不是一个好习惯。