基于Qt的多媒体综合应用程序设计(4)
阅读原文时间:2021年04月23日阅读:1

6.视频播放器
设计过程如下:
1)新建项目:
新建Qt Widgets Application,项目名称为“Player”,勾选ui界面设计选项,基类选择“QWidget”,类名命名为“Player”,并添加该工程的头文件和源文件。
2)完善.pro文件:
在.pro文件中添加如下代码:

QT += network \
      xml \
      multimedia \
      multimediawidgets \
      Widgets

3)实现视频播放器功能
使用传递到qvideowidget中的qmediaplayer对象来控制视频输出。为了提供应用程序播放列表功能,我们还使用qplaylist对象。要激活对话框上的播放和停止等各种功能,单击按钮的事件会发出play()和stop()信号,这些信号连接到qmediaplayer的play()和stop()插槽。关键代码如下:

connect(controls, SIGNAL(play()), player, SLOT(play()));
connect(controls, SIGNAL(pause()), player, SLOT(pause()));
connect(controls, SIGNAL(stop()), player, SLOT(stop()));

打开电脑中的文件,其程序代码如下:

void Player::open()
{
    QFileDialog fileDialog(this);
    fileDialog.setAcceptMode(QFileDialog::AcceptOpen);
    fileDialog.setWindowTitle(tr("Open Files"));
    QStringList supportedMimeTypes = m_player->supportedMimeTypes();
    if (!supportedMimeTypes.isEmpty()) {
        supportedMimeTypes.append("audio/x-m3u"); // MP3 playlists
        fileDialog.setMimeTypeFilters(supportedMimeTypes);
    }
    fileDialog.setDirectory(QStandardPaths::standardLocations(QStandardPaths::MoviesLocation).value(0, QDir::homePath()));
    if (fileDialog.exec() == QDialog::Accepted)
        addToPlaylist(fileDialog.selectedUrls());
}

该部分效果如图3-27所示:

图3-27 打开电脑中的视频文件
播放视频的效果如图3-28所示:

图3-28 播放列表中的视频
4)获取volume并设置用户界面,关键程序代码如下:

controls->setvolume(player->volume());

5)实现音量调节功能,关键代码如下:

connect(controls, SIGNAL(changeVolume(int)), player, SLOT(setVolume(int)));

7)通过qvideowidget对象更改各种视频属性。可以通过单击一个按钮进入全屏模式,然后再次返回。按下“视频调整”对话框按钮,可以接触到更微妙的功能,该对话框有一组滑块,用来更改正在观看的视频的亮度、对比度、色调和饱和度。connect()语句成对出现,因此对用户界面小部件(相关滑块)或qvideowidget对象的更改将更新另一个对象。关键代码如下:

connect(brightnessSlider, SIGNAL(sliderMoved(int)), videoWidget,
      SLOT(setBrightness(int)));
  connect(videoWidget, SIGNAL(brightnessChanged(int)),
      brightnessSlider, SLOT(setValue(int)));
  connect(contrastSlider, SIGNAL(sliderMoved(int)), videoWidget,
      SLOT(setContrast(int)));
  connect(videoWidget, SIGNAL(contrastChanged(int)), contrastSlider,
      SLOT(setValue(int)));
  connect(hueSlider, SIGNAL(sliderMoved(int)), videoWidget,
      SLOT(setHue(int)));
  connect(videoWidget, SIGNAL(hueChanged(int)), hueSlider,
      SLOT(setValue(int)));
  connect(saturationSlider, SIGNAL(sliderMoved(int)), videoWidget,
      SLOT(setSaturation(int)));
  connect(videoWidget, SIGNAL(saturationChanged(int)),
      saturationSlider, SLOT(setValue(int)));

暂停正在播放的视频的效果如图3-29所示:

图3-29 暂停正在播放的视频
播放倍速下拉列表如图3-30所示:

图3-30 倍速播放下拉列表
全屏效果如图3-31所示:

图3-31 全屏播放
“main.cpp”文件的程序代码如下:

#include <QApplication>
#include <QMessageBox>
#include <QMainWindow>
#include <QDesktopWidget>
#include <QVariant>
#include <QSettings>
#include <QFileDialog>
#include <QCommandLineParser>
#include "ui_mainwindow.h"
static const char geometryKey[] = "Geometry";

class MainWindow : public QMainWindow
{
    Q_OBJECT
public:
    MainWindow();
    ~MainWindow();
    void openMedia(const QString &mediaUrl);
public slots:
    void on_mediaPlayer_PlayStateChange(int newState);
    void on_actionOpen_triggered();
    void on_actionExit_triggered();
    void on_actionAbout_triggered();
    void on_actionAboutQt_triggered();
private:
    void updateWindowTitle(const QString &state);
    Ui::MainWindow m_ui;
};
MainWindow::MainWindow()
{
    m_ui.setupUi(this);
    QSettings settings(QSettings::IniFormat, QSettings::UserScope,
                       QCoreApplication::organizationName(), QCoreApplication::applicationName());

    const QByteArray restoredGeometry = settings.value(QLatin1String(geometryKey)).toByteArray();
    if (restoredGeometry.isEmpty() || !restoreGeometry(restoredGeometry)) {
        const QRect availableGeometry = QApplication::desktop()->availableGeometry(this);
        const QSize size = (availableGeometry.size() * 4) / 5;
        resize(size);
        move(availableGeometry.center() - QPoint(size.width(), size.height()) / 2);
    }

    m_ui.mediaPlayer->dynamicCall("enableContextMenu", false);
    m_ui.mediaPlayer->dynamicCall("stretchToFit", true);
    updateWindowTitle("");
}
MainWindow::~MainWindow()
{
    QSettings settings(QSettings::IniFormat, QSettings::UserScope,
                       QCoreApplication::organizationName(), QCoreApplication::applicationName());
    settings.setValue(QLatin1String(geometryKey), saveGeometry());
}
void MainWindow::on_mediaPlayer_PlayStateChange(int newState)
{
    static const QHash<int, const char *> stateMapping {
        {1,  "Stopped"},
        {2,  "Paused"},
        {3,  "Playing"},
        {4,  "Scanning Forwards"},
        {5,  "Scanning Backwards"},
        {6,  "Buffering"},
        {7,  "Waiting"},
        {8,  "Media Ended"},
        {9,  "Transitioning"},
        {10, "Ready"},
        {11, "Reconnecting"},
    };
    const char *stateStr = stateMapping.value(newState, "");
    updateWindowTitle(tr(stateStr));
}
void MainWindow::on_actionOpen_triggered()
{
    QFileDialog fileDialog(this, tr("Open File"));
    fileDialog.setAcceptMode(QFileDialog::AcceptOpen);
    fileDialog.setFileMode(QFileDialog::ExistingFile);
    fileDialog.setMimeTypeFilters({ "application/octet-stream", "video/x-msvideo", "video/mp4", "audio/mpeg", "audio/mp4" });
    if (fileDialog.exec() == QDialog::Accepted)
        openMedia(fileDialog.selectedFiles().first());
}
void MainWindow::on_actionExit_triggered()
{
    QCoreApplication::quit();
}
void MainWindow::on_actionAbout_triggered()
{
    QMessageBox::about(this, tr("About Media Player"),
                tr("This Example has been created using the ActiveQt integration into Qt Designer.\n"
                   "It demonstrates the use of QAxWidget to embed the Windows Media Player ActiveX\n"
                   "control into a Qt application."));
}
void MainWindow::on_actionAboutQt_triggered()
{
    QMessageBox::aboutQt(this, tr("About Qt"));
}
void MainWindow::openMedia(const QString &mediaUrl)
{
    if (!mediaUrl.isEmpty())
        m_ui.mediaPlayer->dynamicCall("URL", mediaUrl);
}
void MainWindow::updateWindowTitle(const QString &state)
{
    QString appName = QCoreApplication::applicationName();
    QString title = state.isEmpty() ? appName :
                    QString("%1 (%2)").arg(appName, state);
    setWindowTitle(title);
}

#include "main.moc"
int main(int argc, char *argv[])
{
    QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    QApplication app(argc, argv);
    QCoreApplication::setApplicationVersion(QT_VERSION_STR);
    QCoreApplication::setApplicationName(QLatin1String("Active Qt Media Player"));
    QCoreApplication::setOrganizationName(QLatin1String("QtProject"));
    MainWindow w;
    QCommandLineParser parser;
    parser.setApplicationDescription(QCoreApplication::applicationName());
    parser.addHelpOption();
    parser.addVersionOption();
    parser.addPositionalArgument("file", "The media file to open.");
    parser.process(app);
    if (!parser.positionalArguments().isEmpty())
        w.openMedia(parser.positionalArguments().constFirst());
    w.show();
    return app.exec();
}

视频调整效果如图3-32所示:

图3-32 视频调整

7.动画播放器
设计过程如下:
1)新建项目:
新建Qt Widgets Application,项目名称为“analogclock”,基类为“QWindow",类名命名为“RasterWindow”,并添加该工程的头文件“rasterwindow.h" 和文件“rasterwindow.cpp"。
2)完善头文件:
在头文件中添加需要使用的函数,如RasterWindow、render、exposeEvent和resizeEvent等。
3)创建显示页面:
利用setGeometry函数在屏幕上创建显示页面,本实验中使用 setGeometry(100, 100, 300, 200);创建了一个从屏幕上(100,100)位置开始(即为最左上角的点),显示一个300*200的界面(宽300,高200)。
4)设置窗口显示页面:
利用setTitle设置窗口的标题为“时钟”,使用resize设置窗口的大小为(200,200),然后利用m_timerId = startTimer(1000);启动一个计时器,用每秒来重新绘制时钟。
5)设计指针:
在绘制时钟之前,先定义三个Qpoints列表和三个Qcolors,用于时针、分针和秒针,设置指针的大小、颜色和透明度,比如QColor secondColor(0, 127, 221, 191);中秒针的颜色alpha分量为191,这意味着它的透明度为75%。
用qpainer::Antialiasing调用qpainer::setrenderInt()以打开反锯齿,使对角线的绘制更加平滑。
利用 p->translate(width() / 2, height() / 2);将原点移动到窗口的中心,缩放操作可确保以下绘图操作缩放以适合窗口,绘制一个固定大小的钟面,它将被定位和缩放,以便它位于窗口的中心。程序代码如下所示:

// 设置分针
    p->setPen(Qt::NoPen);
    p->setBrush(minuteColor);
    p->save();
    p->rotate(6.0 * (time.minute() + time.second() / 60.0));
    p->drawConvexPolygon(minuteHand, 3);
    p->restore();
    p->setPen(minuteColor);
    for (int j = 0; j < 60; ++j) {
        if ((j % 5) != 0)
            p->drawLine(92, 0, 96, 0);
        p->rotate(6.0);
    }
//设置秒针
    p->setPen(Qt::NoPen);
    p->setBrush(secondColor);
    p->save();
    p->rotate(6.0 * (time.second()));
    p->drawConvexPolygon(secondHand, 3);
    p->restore();
    p->setPen(hourColor);

          for (int k = 0; k < 60; ++k) {
              p->drawLine(96, 0, 96, 0);
              p->rotate(6.0);
          }
}

利用setPen实现画笔,用setBrush实现画刷,画刷用于填充多边形和其他几何图形。将笔设置为qt::nopen,由于指针不需要任何轮廓,所以使用更加适合的纯色画笔。使用drawLine在钟的边缘画出每小时的记号,然后旋转坐标系,以便画笔为下一个作好准备。分针和秒针的绘制及相关操作与时针相同。部分代码如下:

void AnalogClockWindow::render(QPainter *p)
{
    static const QPoint hourHand[3] = {
        QPoint(7, 8),
        QPoint(-7, 8),
        QPoint(0, -50)
    };
    static const QPoint minuteHand[3] = {
        QPoint(7, 8),
        QPoint(-7,8),
        QPoint(0, -70)
    };
    static const QPoint secondHand[3] = {
        QPoint(7, 8),
        QPoint(-7, 8),
        QPoint(0, -90)
    };
    QColor hourColor(0,127,0, 191);
    QColor minuteColor(0, 127, 127, 191);
QColor secondColor(0, 127, 221, 191);
}

时钟的表盘如图3-33所示:

图3-33 时钟的表盘
6)完善主函数,在main函数中添加如下代码:
QGuiApplication app(argc, argv);
AnalogClockWindow clock;
clock.show();
return app.exec();
时钟运行的效果如图3-34所示:

图3-34 时钟运行效果

3.2 消息响应及功能模块设计
设计过程如下:
1)在ImgProcessor类中添加createActions()函数用于创建所有的动作、createMenus()函数用于创建菜单、createToolBars()函数用于创建工具栏;接着声明实现主窗口所需的各个元素,包括菜单、工具栏及各个动作等;最后声明用到的槽函数。关键代码如下:

ImgProcessor::ImgProcessor(QWidget *parent)
    : QMainWindow(parent)
{  
    setWindowTitle(tr("Easy Word"));            //设置窗体标题
    showWidget =new ShowWidget(this);        //(a)
    setCentralWidget(showWidget);
    /* 创建动作、菜单、工具栏的函数 */    
    createActions();
    createMenus();
    createToolBars();
    if(img.load("image.png"))
    {
       //在imageLabel对象中放置图像
        showWidget->imageLabel->setPixmap(QPixmap::fromImage(img));
    }
}

2)添加loadFile()事件处理函数,该函数利用QFile和QTextStream完成具体读取文件内容的工作,关键代码如下:

void ImgProcessor::loadFile(QString filename)
{
    printf("file name:%s\n",filename.data());
    QFile file(filename);
    if(file.open(QIODevice::ReadOnly|QIODevice::Text))
    {
        QTextStream textStream(&file);
        while(!textStream.atEnd())
        {
            showWidget->text->append(textStream.readLine());
            printf("read line\n");
        }
        printf("end\n");
    }
}

3)对象与槽之间的响应流程图如下:

手机扫一扫

移动阅读更方便

阿里云服务器
腾讯云服务器
七牛云服务器

你可能感兴趣的文章