⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 qmovie.cpp

📁 奇趣公司比较新的qt/emd版本
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/******************************************************************************** Copyright (C) 1992-2007 Trolltech ASA. All rights reserved.**** This file is part of the QtGui module of the Qt Toolkit.**** This file may be used under the terms of the GNU General Public** License version 2.0 as published by the Free Software Foundation** and appearing in the file LICENSE.GPL included in the packaging of** this file.  Please review the following information to ensure GNU** General Public Licensing requirements will be met:** http://trolltech.com/products/qt/licenses/licensing/opensource/**** If you are unsure which license is appropriate for your use, please** review the following information:** http://trolltech.com/products/qt/licenses/licensing/licensingoverview** or contact the sales department at sales@trolltech.com.**** In addition, as a special exception, Trolltech gives you certain** additional rights. These rights are described in the Trolltech GPL** Exception version 1.0, which can be found at** http://www.trolltech.com/products/qt/gplexception/ and in the file** GPL_EXCEPTION.txt in this package.**** In addition, as a special exception, Trolltech, as the sole copyright** holder for Qt Designer, grants users of the Qt/Eclipse Integration** plug-in the right for the Qt/Eclipse Integration to link to** functionality provided by Qt Designer and its related libraries.**** Trolltech reserves all rights not expressly granted herein.**** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.******************************************************************************//*!     \class QMovie    \brief The QMovie class is a convenience class for playing movies    with QImageReader.    \ingroup multimedia    First, create a QMovie object by passing either the name of a file or a    pointer to a QIODevice containing an animated image format to QMovie's    constructor. You can call isValid() to check if the image data is valid,    before starting the movie. To start the movie, call start(). QMovie will    enter \l Running state, and emit started() and stateChanged(). To get the    current state of the movie, call state().    To display the movie in your application, you can pass your QMovie object    to QLabel::setMovie(). Example:    \code        QLabel label;        QMovie *movie = new QMovie("animations/fire.gif");        label.setMovie(movie);        movie->start();    \endcode    Whenever a new frame is available in the movie, QMovie will emit    updated(). If the size of the frame changes, resized() is emitted. You can    call currentImage() or currentPixmap() to get a copy of the current    frame. When the movie is done, QMovie emits finished(). If any error    occurs during playback (i.e, the image file is corrupt), QMovie will emit    error().    You can control the speed of the movie playback by calling setSpeed(),    which takes the percentage of the original speed as an argument. Pause the    movie by calling setPaused(true). QMovie will then enter \l Paused state    and emit stateChanged(). If you call setPaused(false), QMovie will reenter    \l Running state and start the movie again. To stop the movie, call    stop().    Certain animation formats allow you to set the background color. You can    call setBackgroundColor() to set the color, or backgroundColor() to    retrieve the current background color.    currentFrameNumber() returns the sequence number of the current frame. The    first frame in the animation has the sequence number 0. frameCount()    returns the total number of frames in the animation, if the image format    supports this. You can call loopCount() to get the number of times the    movie should loop before finishing. nextFrameDelay() returns the number of    milliseconds the current frame should be displayed.    QMovie can be instructed to cache frames of an animation by calling    setCacheMode().    Call supportedFormats() for a list of formats that QMovie supports.    \sa QLabel, QImageReader, {Movie Example}*//*! \enum QMovie::MovieState    This enum describes the different states of QMovie.    \value NotRunning The movie is not running. This is QMovie's initial    state, and the state it enters after stop() has been called or the movie    is finished.    \value Paused The movie is paused, and QMovie stops emitting updated() or    resized(). This state is entered after calling pause() or    setPaused(true). The current frame number it kept, and the movie will    continue with the next frame when unpause() or setPaused(false) is called.    \value Running The movie is running.*//*! \enum QMovie::CacheMode    This enum describes the different cache modes of QMovie.    \value CacheNone No frames are cached (the default).    \value CacheAll All frames are cached.*//*! \fn void QMovie::started()    This signal is emitted after QMovie::start() has been called, and QMovie    has entered QMovie::Running state.*//*! \fn void QMovie::resized(const QSize &size)    This signal is emitted when the current frame has been resized to \a    size. This effect is sometimes used in animations as an alternative to    replacing the frame. You can call currentImage() or currentPixmap() to get a    copy of the updated frame.*//*! \fn void QMovie::updated(const QRect &rect)    This signal is emitted when the rect \a rect in the current frame has been    updated. You can call currentImage() or currentPixmap() to get a copy of the    updated frame.*//*! \fn void QMovie::frameChanged(int frameNumber)    \since 4.1    This signal is emitted when the frame number has changed to    \a frameNumber.  You can call currentImage() or currentPixmap() to get a    copy of the frame.*//*!     \fn void QMovie::stateChanged(QMovie::MovieState state)    This signal is emitted every time the state of the movie changes. The new    state is specified by \a state.    \sa QMovie::state()*//*! \fn void QMovie::error(QImageReader::ImageReaderError error)    This signal is emitted by QMovie when the error \a error occurred during    playback.  QMovie will stop the movie, and enter QMovie::NotRunning state.*//*! \fn void QMovie::finished()    This signal is emitted when the movie has finished.    \sa QMovie::stop()*/#include "qglobal.h"#ifndef QT_NO_MOVIE#include "qmovie.h"#include "qimage.h"#include "qimagereader.h"#include "qpixmap.h"#include "qrect.h"#include "qdatetime.h"#include "qtimer.h"#include "qpair.h"#include "qmap.h"#include "qlist.h"#include "qbuffer.h"#include "private/qobject_p.h"#define QMOVIE_INVALID_DELAY -1class QFrameInfo{public:    QPixmap pixmap;    int delay;    bool endMark;    inline QFrameInfo(bool endMark)        : pixmap(QPixmap()), delay(QMOVIE_INVALID_DELAY), endMark(endMark)    { }        inline QFrameInfo()        : pixmap(QPixmap()), delay(QMOVIE_INVALID_DELAY), endMark(false)    { }        inline QFrameInfo(const QPixmap &pixmap, int delay)        : pixmap(pixmap), delay(delay), endMark(false)    { }        inline bool isValid()    {        return endMark || !(pixmap.isNull() && (delay == QMOVIE_INVALID_DELAY));    }        inline bool isEndMarker()    { return endMark; }        static inline QFrameInfo endMarker()    { return QFrameInfo(true); }};class QMoviePrivate : public QObjectPrivate{    Q_DECLARE_PUBLIC(QMovie)public:    QMoviePrivate(QMovie *qq);    bool isDone();    bool next();    int speedAdjustedDelay(int delay) const;    bool isValid() const;    bool jumpToFrame(int frameNumber);    int frameCount() const;    bool jumpToNextFrame();    QFrameInfo infoForFrame(int frameNumber);    void reset();    inline void enterState(QMovie::MovieState newState) {        movieState = newState;        emit q_func()->stateChanged(newState);    }    // private slots    void _q_loadNextFrame();    void _q_loadNextFrame(bool starting);    QImageReader *reader;    int speed;    QMovie::MovieState movieState;    QRect frameRect;    QPixmap currentPixmap;    int currentFrameNumber;    int nextFrameNumber;    int greatestFrameNumber;    int nextDelay;    int playCounter;    qint64 initialDevicePos;    QMovie::CacheMode cacheMode;    bool haveReadAll;    bool isFirstIteration;    QMap<int, QFrameInfo> frameMap;    QTimer nextImageTimer;};/*! \internal */QMoviePrivate::QMoviePrivate(QMovie *qq)    : reader(0), speed(100), movieState(QMovie::NotRunning),      currentFrameNumber(-1), nextFrameNumber(0), greatestFrameNumber(-1),      nextDelay(0), playCounter(-1),      cacheMode(QMovie::CacheNone), haveReadAll(false), isFirstIteration(true){    q_ptr = qq;    nextImageTimer.setSingleShot(true);}/*! \internal */void QMoviePrivate::reset(){    nextImageTimer.stop();    if (reader->device())        initialDevicePos = reader->device()->pos();    currentFrameNumber = -1;    nextFrameNumber = 0;    greatestFrameNumber = -1;    nextDelay = 0;    playCounter = -1;    haveReadAll = false;    isFirstIteration = true;    frameMap.clear();}/*! \internal */bool QMoviePrivate::isDone(){    return (playCounter == 0);}/*!    \internal    Given the original \a delay, this function returns the    actual number of milliseconds to delay according to    the current speed. E.g. if the speed is 200%, the    result will be half of the original delay.*/int QMoviePrivate::speedAdjustedDelay(int delay) const{    return int( (qint64(delay) * qint64(100) ) / qint64(speed) );}/*!    \internal    Returns the QFrameInfo for the given \a frameNumber.    If the frame number is invalid, an invalid QFrameInfo is    returned.    If the end of the animation has been reached, a    special end marker QFrameInfo is returned.*/QFrameInfo QMoviePrivate::infoForFrame(int frameNumber){    if (frameNumber < 0)        return QFrameInfo(); // Invalid    if (haveReadAll && (frameNumber > greatestFrameNumber)) {        if (frameNumber == greatestFrameNumber+1)            return QFrameInfo::endMarker();        return QFrameInfo(); // Invalid    }    if (cacheMode == QMovie::CacheNone) {        if (frameNumber != currentFrameNumber+1) {            // Non-sequential frame access            if (!reader->jumpToImage(frameNumber)) {                if (frameNumber == 0) {                    // Special case: Attempt to "rewind" so we can loop                    // ### This could be implemented as QImageReader::rewind()                    if (reader->device()->isSequential())                        return QFrameInfo(); // Invalid                    QString fileName = reader->fileName();                    QByteArray format = reader->format();                    QIODevice *device = reader->device();                    QColor bgColor = reader->backgroundColor();                    QSize scaledSize = reader->scaledSize();                    delete reader;                    if (fileName.isEmpty())                        reader = new QImageReader(device, format);                    else                        reader = new QImageReader(fileName, format);                    reader->canRead(); // Provoke a device->open() call                    reader->device()->seek(initialDevicePos);                    reader->setBackgroundColor(bgColor);                    reader->setScaledSize(scaledSize);                } else {                    return QFrameInfo(); // Invalid                }            }        }        if (reader->canRead()) {            // reader says we can read. Attempt to actually read image            QImage anImage = reader->read();            if (anImage.isNull()) {                // Reading image failed.                return QFrameInfo(); // Invalid            }            if (frameNumber > greatestFrameNumber)                greatestFrameNumber = frameNumber;            QPixmap aPixmap = QPixmap::fromImage(anImage);            int aDelay = reader->nextImageDelay();            return QFrameInfo(aPixmap, aDelay);        } else {            // We've read all frames now. Return an end marker            haveReadAll = true;            return QFrameInfo::endMarker();        }    }    // CacheMode == CacheAll    if (frameNumber > greatestFrameNumber) {        // Frame hasn't been read from file yet. Try to do it        for (int i = greatestFrameNumber + 1; i <= frameNumber; ++i) {            if (reader->canRead()) {                // reader says we can read. Attempt to actually read image                QImage anImage = reader->read();                if (anImage.isNull()) {                    // Reading image failed.                    return QFrameInfo(); // Invalid                }                greatestFrameNumber = i;                QPixmap aPixmap = QPixmap::fromImage(anImage);                int aDelay = reader->nextImageDelay();                QFrameInfo info(aPixmap, aDelay);                // Cache it!                frameMap.insert(i, info);                if (i == frameNumber) {                    return info;                }            } else {                // We've read all frames now. Return an end marker                haveReadAll = true;                return QFrameInfo::endMarker();            }        }    }    // Return info for requested (cached) frame    return frameMap.value(frameNumber);}/*!    \internal    Attempts to advance the animation to the next frame.    If successful, currentFrameNumber, currentPixmap and    nextDelay are updated accordingly, and true is returned.    Otherwise, false is returned.    When false is returned, isDone() can be called to    determine whether the animation ended gracefully or    an error occurred when reading the frame.*/bool QMoviePrivate::next(){    QTime time;    time.start();    QFrameInfo info = infoForFrame(nextFrameNumber);    if (!info.isValid())        return false;    if (info.isEndMarker()) {        // We reached the end of the animation.        if (isFirstIteration) {            if (nextFrameNumber == 0) {                // No frames could be read at all (error).                return false;            }            // End of first iteration. Initialize play counter            playCounter = reader->loopCount();            isFirstIteration = false;        }        // Loop as appropriate        if (playCounter != 0) {            if (playCounter != -1) // Infinite?                playCounter--;     // Nope            nextFrameNumber = 0;            return next();        }        // Loop no more. Done        return false;    }    // Image and delay OK, update internal state    currentFrameNumber = nextFrameNumber++;    QSize scaledSize = reader->scaledSize();    if (scaledSize.isValid() && (scaledSize != info.pixmap.size()))        currentPixmap = QPixmap::fromImage( info.pixmap.toImage().scaled(scaledSize) );    else        currentPixmap = info.pixmap;    nextDelay = speedAdjustedDelay(info.delay);    // Adjust delay according to the time it took to read the frame    int processingTime = time.elapsed();    if (processingTime > nextDelay)        nextDelay = 0;    else        nextDelay = nextDelay - processingTime;    return true;}/*! \internal */void QMoviePrivate::_q_loadNextFrame(){    _q_loadNextFrame(false);}void QMoviePrivate::_q_loadNextFrame(bool starting){    Q_Q(QMovie);    if (next()) {        if (starting && movieState == QMovie::NotRunning) {            enterState(QMovie::Running);            emit q->started();        }        if (frameRect.size() != currentPixmap.rect().size()) {            frameRect = currentPixmap.rect();            emit q->resized(frameRect.size());        }        emit q->updated(frameRect);        emit q->frameChanged(currentFrameNumber);        if (movieState == QMovie::Running)            nextImageTimer.start(nextDelay);    } else {        // Could not read another frame        if (!isDone()) {            emit q->error(reader->error());        }        // Graceful finish        if (movieState != QMovie::Paused) {            nextFrameNumber = 0;            isFirstIteration = true;            playCounter = -1;            enterState(QMovie::NotRunning);            emit q->finished();        }    }}/*!    \internal*/bool QMoviePrivate::isValid() const{    return (greatestFrameNumber >= 0) // have we seen valid data        || reader->canRead(); // or does the reader see valid data}/*!    \internal*/bool QMoviePrivate::jumpToFrame(int frameNumber){    if (frameNumber < 0)        return false;    if (currentFrameNumber == frameNumber)        return true;    nextFrameNumber = frameNumber;    if (movieState == QMovie::Running)        nextImageTimer.stop();    _q_loadNextFrame();    return (nextFrameNumber == currentFrameNumber+1);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -