QMovie
类是一个方便的类,用于播放具有QImageReader
的动画。此类用于显示没有声音的简单动画。如果您想显示视频和媒体内容,请改用Qt多媒体框架Qt Multimedia multimedia framework
。
首先,通过将文件的名称或包含动画图像格式的QIODevice
的指针传递给QMovie
的构造函数,创建一个QMovie
对象。您可以在开始播放动画之前调用isValid()
函数来检查图像数据是否有效。要开始播放动画,请调用start()
函数。QMovie
将进入Running
状态,并发出started()
和stateChanged()
信号。要获取动画的当前状态,请调用state()
函数。
要在应用程序中显示动画,您可以将QMovie
对象传递给QLabel::setMovie()
函数。示例如下:
QLabel label;
QMovie *movie = new QMovie("animations/fire.gif");
label.setMovie(movie);
movie->start();
每当动画中有新帧可用时,QMovie
将发出updated()
信号。如果帧的大小发生更改,则发出resized()
信号。您可以调用currentImage()
或currentPixmap()
函数来获取当前帧的副本。当动画完成时,QMovie
发出finished()
信号。如果在播放过程中发生任何错误(即,图像文件损坏),QMovie
将发出error()
信号。
调用setSpeed()
函数可以控制动画的播放速度,该函数将原始速度的百分比作为参数。通过调用setPaused(true)
函数可以暂停动画。然后,QMovie
将进入Paused
状态,并发出stateChanged()
信号。如果调用setPaused(false)
函数,则QMovie
将重新进入Running
状态并重新开始动画。要停止动画,请调用stop()
函数。
某些动画格式允许您设置背景颜色。您可以调用setBackgroundColor()
函数来设置颜色,或者调用backgroundColor()
函数来获取当前的背景颜色。
currentFrameNumber()
函数返回当前帧的序列号。动画中的第一帧序列号为0
。如果图像格式支持,frameCount()
函数返回动画中的总帧数。可以调用loopCount()
函数获取动画在完成之前应循环播放的次数。nextFrameDelay()
函数返回当前帧应该显示的毫秒数。
可以通过调用setCacheMode()
函数,指示QMovie
缓存动画的帧。
调用supportedFormats()
函数可以获取QMovie
支持的格式列表。
enum CacheMode { CacheNone, CacheAll }
// 缓存模式enum MovieState { NotRunning, Paused, Running }
// 动画状态cacheMode : CacheMode
// 缓存模式speed : int
// 速度QMovie(QObject *parent = Q_NULLPTR)
// 构造函数int currentFrameNumber() const
// 获取当前帧的序号QImage currentImage() const
// 获取当前帧的QImage对象QRect frameRect() const
// 获取动画帧的矩形区域bool isValid() const
// 检查动画数据是否有效bool jumpToFrame(int frameNumber)
// 跳转到指定帧int nextFrameDelay() const
// 获取下一帧的延迟时间void setCacheMode(CacheMode mode)
// 设置缓存模式int speed() const
// 获取速度MovieState state() const
// 获取动画状态先上UI:
实现步骤在代码中有注释。
MoviePlayer.h
#ifndef MOVIEPLAYER_H
#define MOVIEPLAYER_H
#include
QT_BEGIN_NAMESPACE
class QCheckBox;
class QGridLayout;
class QHBoxLayout;
class QLabel;
class QMovie;
class QSlider;
class QSpinBox;
class QToolButton;
class QVBoxLayout;
QT_END_NAMESPACE
class MoviePlayer : public QWidget
{
Q_OBJECT
public:
MoviePlayer(QWidget *parent = 0);
// 打开文件
void openFile(const QString &fileName);
private slots:
// 打开槽函数
void open();
// 跳转到某帧
void goToFrame(int frame);
// 适应窗口
void fitToWindow();
// 更新按钮状态
void updateButtons();
// 更新帧滑动条
void updateFrameSlider();
// 当微调框数据改变时,触发此槽
void slot_valueChanged(int nPercentSpeed);
private:
// 创建控件
void createControls();
// 创建按钮:开始、暂停、停止
void createButtons();
// 目录
QString currentMovieDirectory;
QLabel *movieLabel; // 防止QMoive的控件
QMovie *movie; // QMoive对象
QToolButton *openButton;
QToolButton *playButton;
QToolButton *pauseButton;
QToolButton *stopButton;
QToolButton *quitButton;
QCheckBox *fitCheckBox;
QSlider *frameSlider;
QSpinBox *speedSpinBox;
QLabel *frameLabel;
QLabel *speedLabel;
QGridLayout *controlsLayout;
QHBoxLayout *buttonsLayout;
QVBoxLayout *mainLayout;
};
#endif
MoviePlayer.cpp
#include
#include "movieplayer.h"
MoviePlayer::MoviePlayer(QWidget *parent)
: QWidget(parent)
{
movie = new QMovie(this);
movie->setCacheMode(QMovie::CacheAll);
movieLabel = new QLabel(tr("No movie loaded"));
movieLabel->setAlignment(Qt::AlignCenter);
movieLabel->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
movieLabel->setBackgroundRole(QPalette::Dark);
movieLabel->setAutoFillBackground(true);
currentMovieDirectory = "movies";
createControls();
createButtons();
connect(movie, SIGNAL(frameChanged(int)), this, SLOT(updateFrameSlider()));
connect(movie, SIGNAL(stateChanged(QMovie::MovieState)),
this, SLOT(updateButtons()));
connect(fitCheckBox, SIGNAL(clicked()), this, SLOT(fitToWindow()));
connect(frameSlider, SIGNAL(valueChanged(int)), this, SLOT(goToFrame(int)));
connect(speedSpinBox, SIGNAL(valueChanged(int)),
this, SLOT(slot_valueChanged(int)));
// movie, SLOT(setSpeed(int)));
mainLayout = new QVBoxLayout;
mainLayout->addWidget(movieLabel);
mainLayout->addLayout(controlsLayout);
mainLayout->addLayout(buttonsLayout);
setLayout(mainLayout);
updateFrameSlider();
updateButtons();
setWindowTitle(tr("Movie Player"));
resize(400, 400);
}
void MoviePlayer::open()
{
QString fileName = QFileDialog::getOpenFileName(this, tr("Open a Movie"),
currentMovieDirectory);
if (!fileName.isEmpty())
openFile(fileName);
}
void MoviePlayer::openFile(const QString &fileName)
{
currentMovieDirectory = QFileInfo(fileName).path();
movie->stop();
movieLabel->setMovie(movie);
movie->setFileName(fileName);
movie->start();
updateFrameSlider();
updateButtons();
}
void MoviePlayer::goToFrame(int frame)
{
movie->jumpToFrame(frame);
}
void MoviePlayer::fitToWindow()
{
movieLabel->setScaledContents(fitCheckBox->isChecked());
}
void MoviePlayer::updateFrameSlider()
{
bool hasFrames = (movie->currentFrameNumber() >= 0);
if (hasFrames) {
if (movie->frameCount() > 0) {
frameSlider->setMaximum(movie->frameCount() - 1);
} else {
if (movie->currentFrameNumber() > frameSlider->maximum())
frameSlider->setMaximum(movie->currentFrameNumber());
}
frameSlider->setValue(movie->currentFrameNumber());
} else {
frameSlider->setMaximum(0);
}
frameLabel->setEnabled(hasFrames);
frameSlider->setEnabled(hasFrames);
}
void MoviePlayer::slot_valueChanged(int nPercentSpeed)
{
qDebug().noquote() << "[" << __FILE__ << __LINE__ << "]" << "nPercentSpeed :" << nPercentSpeed;
movie->setSpeed(nPercentSpeed);
}
void MoviePlayer::updateButtons()
{
playButton->setEnabled(movie->isValid() && movie->frameCount() != 1
&& movie->state() == QMovie::NotRunning);
pauseButton->setEnabled(movie->state() != QMovie::NotRunning);
pauseButton->setChecked(movie->state() == QMovie::Paused);
stopButton->setEnabled(movie->state() != QMovie::NotRunning);
}
void MoviePlayer::createControls()
{
fitCheckBox = new QCheckBox(tr("Fit to Window"));
frameLabel = new QLabel(tr("Current frame:"));
frameSlider = new QSlider(Qt::Horizontal);
frameSlider->setTickPosition(QSlider::TicksBelow);
frameSlider->setTickInterval(10);
speedLabel = new QLabel(tr("Speed:"));
speedSpinBox = new QSpinBox;
speedSpinBox->setRange(1, 9999);
speedSpinBox->setValue(100);
speedSpinBox->setSuffix(tr("%"));
controlsLayout = new QGridLayout;
controlsLayout->addWidget(fitCheckBox, 0, 0, 1, 2);
controlsLayout->addWidget(frameLabel, 1, 0);
controlsLayout->addWidget(frameSlider, 1, 1, 1, 2);
controlsLayout->addWidget(speedLabel, 2, 0);
controlsLayout->addWidget(speedSpinBox, 2, 1);
}
void MoviePlayer::createButtons()
{
QSize iconSize(36, 36);
openButton = new QToolButton;
openButton->setIcon(style()->standardIcon(QStyle::SP_DialogOpenButton));
openButton->setIconSize(iconSize);
openButton->setToolTip(tr("Open File"));
connect(openButton, SIGNAL(clicked()), this, SLOT(open()));
playButton = new QToolButton;
playButton->setIcon(style()->standardIcon(QStyle::SP_MediaPlay));
playButton->setIconSize(iconSize);
playButton->setToolTip(tr("Play"));
connect(playButton, SIGNAL(clicked()), movie, SLOT(start()));
pauseButton = new QToolButton;
pauseButton->setCheckable(true);
pauseButton->setIcon(style()->standardIcon(QStyle::SP_MediaPause));
pauseButton->setIconSize(iconSize);
pauseButton->setToolTip(tr("Pause"));
connect(pauseButton, SIGNAL(clicked(bool)), movie, SLOT(setPaused(bool)));
stopButton = new QToolButton;
stopButton->setIcon(style()->standardIcon(QStyle::SP_MediaStop));
stopButton->setIconSize(iconSize);
stopButton->setToolTip(tr("Stop"));
connect(stopButton, SIGNAL(clicked()), movie, SLOT(stop()));
quitButton = new QToolButton;
quitButton->setIcon(style()->standardIcon(QStyle::SP_DialogCloseButton));
quitButton->setIconSize(iconSize);
quitButton->setToolTip(tr("Quit"));
connect(quitButton, SIGNAL(clicked()), this, SLOT(close()));
buttonsLayout = new QHBoxLayout;
buttonsLayout->addStretch();
buttonsLayout->addWidget(openButton);
buttonsLayout->addWidget(playButton);
buttonsLayout->addWidget(pauseButton);
buttonsLayout->addWidget(stopButton);
buttonsLayout->addWidget(quitButton);
buttonsLayout->addStretch();
}
调用
#include
#include "movieplayer.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
MoviePlayer player;
player.show();
player.show();
return app.exec();
}
QMovie
来实现等待界面。QMovie
类也适用于在应用程序中显示电影。通过将QMovie
对象传递给QLabel::setMovie()
,可以将动画显示在QLabel
控件中。总之,QMovie
类适用于需要播放简单动画或实现等待界面的各种场景。