Qt控件之QMovies
- 概述
- 公共类型
- 属性
- 公共函数
- 公共槽函数
- 信号
- 静态公共成员
- 示例
- 使用场景
概述
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)
// 构造函数- QMovie(QIODevice *device, const QByteArray &format = QByteArray(), QObject *parent = Q_NULLPTR)
- QMovie(const QString &fileName, const QByteArray &format = QByteArray(), QObject *parent = Q_NULLPTR)
- ~QMovie() // 析构函数
- QColor backgroundColor() const // 获取背景颜色
- CacheMode cacheMode() const // 获取缓存模式
int currentFrameNumber() const
// 获取当前帧的序号QImage currentImage() const
// 获取当前帧的QImage对象- QPixmap currentPixmap() const // 获取当前帧的QPixmap对象
- QIODevice *device() const // 获取当前设备
- QString fileName() const // 获取文件名
- QByteArray format() const // 获取格式
- int frameCount() const // 获取动画的总帧数
QRect frameRect() const
// 获取动画帧的矩形区域bool isValid() const
// 检查动画数据是否有效bool jumpToFrame(int frameNumber)
// 跳转到指定帧- int loopCount() const // 获取动画应循环播放的次数
int nextFrameDelay() const
// 获取下一帧的延迟时间- QSize scaledSize() // 获取缩放尺寸
- void setBackgroundColor(const QColor &color) // 设置背景颜色
void setCacheMode(CacheMode mode)
// 设置缓存模式- void setDevice(QIODevice *device) // 设置设备
- void setFileName(const QString &fileName) // 设置文件名
- void setFormat(const QByteArray &format) // 设置格式
- void setScaledSize(const QSize &size) // 设置缩放尺寸
int speed() const
// 获取速度MovieState state() const
// 获取动画状态
公共槽函数
- bool jumpToNextFrame() // 跳转到下一帧
- void setPaused(bool paused) // 设置暂停状态
- void setSpeed(int percentSpeed) // 设置速度
- void start() // 开始播放动画
- void stop() // 停止动画
信号
- void error(QImageReader::ImageReaderError error) // 错误信号
- void finished() // 动画完成信号
- void frameChanged(int frameNumber) // 帧变化信号
- void resized(const QSize &size) // 重新调整大小信号
- void started() // 动画开始信号
- void stateChanged(QMovie::MovieState state) // 状态变化信号
- void updated(const QRect &rect) // 更新信号
静态公共成员
- QList supportedFormats() // 支持的格式列表
示例
先上UI:
实现步骤在代码中有注释。
MoviePlayer.h
#ifndef MOVIEPLAYER_H
#define MOVIEPLAYER_H
#include <QWidget>
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 <QtWidgets>
#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 <QApplication>
#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
类适用于需要播放简单动画或实现等待界面的各种场景。