Qt网编实现音乐播放器的使用(Linux搭建服务器)

一、界面效果

            

功能:

搜索歌曲:客户端用户输入歌曲名,点击显示歌曲信息,服务器根据客户端发送来的名字在歌曲表内查询查询到的话,则将对应的歌曲文件数据发送到客户端新创建的一个文件夹内,然后加入到多媒体播放。(最后关闭窗口会直接删除此文件夹)

添加歌单:客户端用户觉得搜索到的此首歌曲可以,可将该歌曲添加到服务器端自己的歌单表内。

下载歌曲:客户可根据搜索到的此首歌曲,将此歌曲下载到客户端内选择的文件夹内。

歌曲选择:客户可选择自己的本地下载过的歌曲加入列表播放。

显示歌单:客户端用户调用服务器数据库内自己的表,将表内歌单显示在客户端列表内。

播放选择:

通过歌曲选择在列表内的歌单

正常的播放/暂停,上下歌切换,进度条的调节,单曲/顺序/随机播放等

(注:歌曲列表显示的是服务器发送过来的数据 上下歌切换关闭)

        部分代码:

        音乐播放器界面:

        

#include "musicwin.h"
#include "ui_musicwin.h"
#include <QFileDialog>
#include <QTime>
#include <QTimer>
#include <QFileInfo>
#include <QDebug>
#include <QByteArray>
#include <network.h>
#include <QMessageBox>
#include <QtEndian>
#include <QtGlobal>
#include <winsock2.h>
#include<QTextCodec> //引入
#include <QPainter>
musicwin::musicwin(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::musicwin)
{
    this->dirName = "C:\\Users\\Administrator\\Desktop\\QT_Project\\day4_musicWork\\TemporaryMusic";
    this->times = 0;
    this->j = 0;
    this->flag = 0;
    this->size = 0;
    this->all = 0;
    this->dirName = nullptr;
    this->file = NULL;
    this->row = 0;
    ui->setupUi(this);
    this->Icount = 0;
    this->n = 0;
    this->mediaPlayer = new QMediaPlayer(this);
    this->music = new QByteArray;
    this->music->clear();
    this->exist = -1;
    ui->label->setText("00:00/00:00");
    //设置播放/暂停的图标
    this->ui->pushButton_play->setIcon(this->style()->standardIcon(QStyle::SP_MediaPlay));
    //设置上一曲和下一曲的图标
    this->ui->pushButton_last->setIcon(this->style()->standardIcon(QStyle::SP_MediaSeekBackward));
    this->ui->pushButton_next->setIcon(this->style()->standardIcon(QStyle::SP_MediaSeekForward));
    //设置按钮图标
    this->ui->searchBtn->setIcon(QIcon(":/image/搜索.png"));
    this->ui->downloadBtn->setIcon(QIcon(":/image/下载.png"));
    this->ui->showBtn->setIcon(QIcon(":/image/查看.png"));
    this->ui->collectBtn->setIcon(QIcon(":/image/收藏.png"));
    this->ui->pushButton_choose->setIcon(QIcon(":/image/选择.png"));
    this->ui->pushButton->setIcon(QIcon(":/image/刷新.png"));
    //设置音量调节进度条的取值范围和初始值
    this->ui->volumeSlider->setRange(0, 100);
    this->ui->volumeSlider->setValue(30);
    this->timer = new QTimer(this);
    //设置编辑框后虚内容显示
    this->ui->searchEdit->setPlaceholderText("歌曲搜索");
    //绘制背景图
    QPalette pal = this->palette();
    pal.setBrush(QPalette::Background, QBrush(QPixmap(":/image/音乐.jpg")));
    setPalette(pal);
    //滚动显示歌曲名称
    connect(this->timer, SIGNAL(timeout()), this, SLOT(showMusicName()));
    //根据位置的变化来设置进度条的位置
    connect(this->mediaPlayer, SIGNAL(positionChanged(qint64)), this, SLOT(updatePlaySlider(qint64)));
    //根据时长的变化来获取播放的总时长设置给进度条的范围
    connect(this->mediaPlayer, SIGNAL(durationChanged(qint64)), this, SLOT(setPlaySliderRange(qint64)));
}

musicwin::~musicwin()
{
    delete ui;
}



void musicwin::on_pushButton_choose_clicked()
{
    //清空编辑框
    this->ui->searchEdit->clear();
    //如果选择本地歌曲设置上下切换为可按状态
    this->ui->pushButton_last->setEnabled(true);
    this->ui->pushButton_next->setEnabled(true);
    this->ui->listWidget->clear();
    //打开文件选择歌曲 获取歌曲路径加入列表
    this->fileList = QFileDialog::getOpenFileNames(this, "选择", ".", "MP3(*.MP3)");
    //默认选择的歌曲从第一首开始 获取路径
    this->musicPath = fileList.at(0);
    //获取根据路径获取名称
    QFileInfo fileInfo(musicPath);
    //显示第一首的歌曲信息 转换获取歌曲名
    this->musicName = fileInfo.fileName();
    this->name = this->musicName + "   ";
    this->ui->label_2->setText(this->name);
    //将选中的歌曲添加列表框内
    int i;
    for (i = 0; i < this->fileList.size(); i++)
    {
        QFileInfo fileInfo(this->fileList.at(i));
        this->ui->listWidget->addItem(fileInfo.baseName());
    }
    //将第一首歌曲加入播放器中
    this->mediaPlayer->setMedia(QUrl(this->musicPath));
    //显示正在播放的歌曲
    this->ui->listWidget->setCurrentRow(0);
    //开始播放第一首音乐
    this->mediaPlayer->play();
    //启动定时器让歌曲名称进行滚动显示
    this->timer->start(1000);
    //播放开始的时候将播放的按钮由播放设置为暂停
    this->ui->pushButton_play->setIcon(this->style()->standardIcon(QStyle::SP_MediaPause));
}
//滚动显示选中的歌曲名称
void musicwin::showMusicName()
{
    this->n++;
    if (this->n  == this->name.size())
    {
        this->n = 0;
    }
    this->ui->label_2->setText(this->name.mid(this->n));
    //显示总时长--毫秒
    qint64 dur = this->mediaPlayer->duration();
    //显示当前播放时长--毫秒
    qint64 pos = this->mediaPlayer->position();
    //实例化时间对象 动态显示时间
    QTime time1(0, 0, 0), time2(0, 0, 0);
    this->ui->label->setText(time1.addMSecs(int(pos)).toString("mm:ss") + "/"
                             + time2.addMSecs(int(dur)).toString("mm:ss"));
    //判断歌曲是否播放完成
    if (dur == pos)
    {
        if ("顺序播放" == ui->comboBox->currentText())
        {
            this->n = ui->listWidget->currentRow();
            if (n == this->fileList.size() - 1)
            {
                //再次从0开始
                n = -1;
            }
            //按照顺序执行列表框内的歌单
            this->musicPath = this->fileList.at(n + 1);
            //播放音乐
            this->mediaPlayer->setMedia(QUrl(this->musicPath));
            //列表显示到歌曲名称
            this->ui->listWidget->setCurrentRow(n + 1);
            //滚动显示歌曲名称
            QFileInfo fileInfo(this->musicPath);
            this->musicName = fileInfo.fileName();
            this->name = this->musicName + "   ";
            this->ui->label_2->setText(this->name);
            //开始播放
            this->mediaPlayer->play();
            this->timer->start(1000);
        }
        else if ("循环播放" == ui->comboBox->currentText())
        {
            //循环播放 stop让这个播放器停止再次打开 从头开始 不改变其内容
            this->mediaPlayer->stop();
            this->mediaPlayer->play();
        }
        else if ("随机播放" == ui->comboBox->currentText())
        {
            //使用随机函数获取随机值
            int num = qrand() % (this->fileList.size() - 1);
            this->musicPath = this->fileList.at(num);
            //播放音乐
            this->mediaPlayer->setMedia(QUrl(this->musicPath));
            //列表显示到歌曲名称
            this->ui->listWidget->setCurrentRow(num);
            //滚动显示歌曲名称
            QFileInfo fileInfo(this->musicPath);
            this->musicName = fileInfo.fileName();
            this->name = this->musicName + "   ";
            this->ui->label_2->setText(this->name);
            //开始播放
            this->mediaPlayer->play();
            this->timer->start(1000);
        }
    }
}
//修改播放进度条
void musicwin::updatePlaySlider(qint64 position)
{
    //根据歌曲的修改位置设置播放进度条的位置
    this->ui->viewSlider->setValue(int(position));
}

void musicwin::setPlaySliderRange(qint64 duration)
{
    //根据选中歌曲的总范围设置播放进度条的设置
    this->ui->viewSlider->setRange(0, int(duration));
}
void musicwin::on_pushButton_play_clicked()
{
    //获取当前播放音乐的状态
    int state = this->mediaPlayer->state();
    //如果当前为播放状态
    if (state == QMediaPlayer::PlayingState)
    {
        //设置播放器为暂停态
        this->mediaPlayer->pause();
        //修改按钮显示为暂停
        this->ui->pushButton_play->setIcon(this->style()->standardIcon(QStyle::SP_MediaPlay));
    }
    //如果当前为暂停态
    else if (state == QMediaPlayer::PausedState)
    {
        //设置为播放器播放态
        this->mediaPlayer->play();
        //修改按钮显示为播放
        this->ui->pushButton_play->setIcon(this->style()->standardIcon(QStyle::SP_MediaPause));
    }
}
//根据播放进度滑块的位置来设置歌曲播放的位置
void musicwin::on_viewSlider_sliderMoved(int position)
{
    this->mediaPlayer->setPosition(position);
}
//根据音量滑块的位置来设置歌曲播放的音量
void musicwin::on_volumeSlider_sliderMoved(int position)
{
    this->mediaPlayer->setVolume(position);
}
//上一首
void musicwin::on_pushButton_last_clicked()
{
    int pos = this->ui->listWidget->currentRow();
    if (0 == pos)
    {
        //如果是第一首点击上一首则跳到最后一首
        pos = this->fileList.size();
    }
    //获取上一首的路径 也就是当前的减一 列表内的上一个
    this->musicPath = this->fileList.at(pos - 1);
    //播放音乐
    this->mediaPlayer->setMedia(QUrl(this->musicPath));
    //列表显示到上一首歌曲名称
    this->ui->listWidget->setCurrentRow(pos - 1);
    //滚动显示歌曲名称
    QFileInfo fileInfo(this->musicPath);
    this->musicName = fileInfo.baseName();
    this->name = this->musicName + "   ";
    this->ui->label_2->setText(this->name);
    //开始播放
    this->mediaPlayer->play();
    this->timer->start(1000);
}

void musicwin::on_pushButton_next_clicked()
{
    int pos = this->ui->listWidget->currentRow();
    if (pos == this->fileList.size() - 1)
    {
        //如果是最后一首点击下一首则跳到第一首
        pos = -1;
    }
    //获取下一首的路径 也就是当前的加一 列表内的下一个
    this->musicPath = this->fileList.at(pos + 1);
    //播放音乐
    this->mediaPlayer->setMedia(QUrl(this->musicPath));
    //列表显示到下一首歌曲名称
    this->ui->listWidget->setCurrentRow(pos + 1);
    //滚动显示歌曲名称
    QFileInfo fileInfo(this->musicPath);
    this->musicName = fileInfo.baseName();
    this->name = this->musicName + "   ";
    this->ui->label_2->setText(this->name);
    //开始播放
    this->mediaPlayer->play();
    this->timer->start(1000);
}
//双击列表框内切换歌曲
void musicwin::on_listWidget_itemDoubleClicked(QListWidgetItem *item)
{
    //获取当前列表内对应的第几行
    int pos = this->ui->listWidget->currentRow();
    //获取当前歌曲的路径
    this->musicPath = this->fileList.at(pos);
    qDebug() << pos;
    //播放音乐
    this->mediaPlayer->setMedia(QUrl(this->musicPath));
    //滚动显示歌曲名称
    QFileInfo fileInfo(this->musicPath);
    this->musicName = fileInfo.baseName();
    this->name = this->musicName + "   ";
    this->ui->label_2->setText(this->name);
    //开始播放
    this->mediaPlayer->play();
    this->timer->start(1000);
}
//搜索歌曲
void musicwin::on_searchBtn_clicked()
{
    ui->label->setText("00:00/00:00");
    this->name = "    ";
    this->timer->stop();
    this->ui->listWidget->clear();
    //如果有音乐正在播放 一切内容清空
    //路径清空
    this->musicPath.clear();
    this->mediaPlayer->stop();
    QMessageBox::information(this, "提示框", "抱歉用户系统不够完善,请于最少10s后点击刷新进行歌曲播放");
    //获取套接字
    NetWork *w = NetWork::getNet();
    disconnect(w->socket, SIGNAL(readyRead()), this, SLOT(showMyMusic()));
    disconnect(w->socket, SIGNAL(readyRead()), this, SLOT(ensureCollect()));
    //读完缓存区内容
    QString recv = w->socket->readAll();
    //获取编辑框内容
    char str[100] = {'\0'};
    QByteArray data = this->ui->searchEdit->text().toUtf8();
    sprintf(str, "Search#%s", data.data());
    connect(w->socket, SIGNAL(readyRead()), this, SLOT(readData()));
    //将数据发送过去
    w->socket->write(str);
}

void musicwin::readData()
{
    NetWork *w = NetWork::getNet();
    if (this->j == 0) //获取到歌曲名称
    {
        QByteArray data = w->socket->read(50);
        this->row = QString(data).toInt();
        if (this->row > 0)
        {
            this->row = 0;
            //创建临时文件夹
            setDir();
            //UTF-8 GBK类型转换
            this->musicPath = this->dirName + "/" + this->ui->searchEdit->text() + ".mp3";
            QTextCodec *code = QTextCodec::codecForName("GB2312");
            std::string name = code->fromUnicode(this->musicPath).data();
            qDebug() << this->musicPath;
            FILE *file = fopen(name.c_str(), "wb+");
            if (file == NULL)
            {
                qDebug() << "打开文件失败";
                return;
            }
            this->file = file;
            this->ui->listWidget->clear();
            this->ui->listWidget->addItem(this->ui->searchEdit->text());
            this-> j = 1;
        }
        else if (this->row == 0)
        {
            QMessageBox::information(this, "提示框", "抱歉用户,该歌曲不存在");
            this->ui->searchEdit->clear();
            this->ui->listWidget->clear();
            //断掉连接 为了下次连接正确
            NetWork *w = NetWork::getNet();
            disconnect(w->socket, SIGNAL(readyRead()), this, SLOT(readData()));
            this->j = 0;
        }
    }
    else if (this->j == 1) //获取文件大小
    {
        qDebug() << "文件大小";
        QByteArray recv = w->socket->readAll();// 大小
        QString str = QString(recv);
        //得到了音乐文件的大小
        this->size = str.split("#").at(1).toInt();
        qDebug() << this->size;
        this->j = 2;
    }
    else if (this->j == 2)
    {
        //读前4字节获取读多少数据
        QByteArray recv = w->socket->read(4);
        u_long count = 0;
        memcpy(&count, recv.data(), 4);
        count = ntohl(count);
        this->Icount = count;
        //读后4字节获取读到的第几个包
        QByteArray bag = w->socket->read(4);
        u_long many = 0;
        memcpy(&many, bag.data(), 4);
        many = ntohl(many);
        //读8个字节后的数据
        QByteArray data = w->socket->read(count);
        this->music->append(data);
        this->all = this->all + count;
        qDebug() << QString::number(this->all) + "/" + QString::number(this->size);
        fwrite(data.toStdString().c_str(), count, 1, file);
    }
}

void musicwin::setDir()
{
    QFileInfo info("./day4_musicWork.exe");
    QString absolutePath = info.absolutePath();
    //创建临时文件夹
    this->dirName = absolutePath + "/" + "TemporaryMusic";
    QDir dir(dirName);
    if (!dir.exists())
    {
        dir.mkdir(dirName);
        qDebug() << "文件夹创建成功";
    }
}
//刷新读数据
void musicwin::on_pushButton_clicked()
{
    while (1)
    {
        readData();
        if (this->Icount != 1000)
        {
            qDebug() << this->musicPath;
            fclose(file);
            this->file = NULL;
            this->j = 0;
            this->all = 0;
            //断开信号
            NetWork *w = NetWork::getNet();
            QByteArray rec = w->socket->readAll();
            disconnect(w->socket, SIGNAL(readyRead()), this, SLOT(readData()));
            break;
        }
    }
    QMessageBox::information(this, "提示框", "歌曲开始播放");
    //此时歌曲播放
    //播放音乐
    this->mediaPlayer->setMedia(QUrl(this->musicPath));
    //滚动显示歌曲名称
    QFileInfo fileInfo(this->musicPath);
    this->musicName = fileInfo.baseName();
    this->name = this->musicName + "   ";
    this->ui->label_2->setText(this->name);
    //开始播放
    this->mediaPlayer->play();
    this->timer->start(1000);
    //播放开始的时候将播放的按钮由播放设置为暂停
    this->ui->pushButton_play->setIcon(this->style()->standardIcon(QStyle::SP_MediaPause));
    //设置上下首为不可按状态
    this->ui->pushButton_last->setEnabled(false);
    this->ui->pushButton_next->setEnabled(false);
    return;
}
//重新关闭函数
void musicwin::closeEvent(QCloseEvent *e)
{
    int ret = QMessageBox::question(this, "提示框", "是否确认退出");
    if (ret != QMessageBox::Yes)
    {
        e->ignore();
        return;
    }
    DelDir(this->dirName);
    exit(0);
}

//删除临时文件夹
bool musicwin::DelDir(const QString &path)
{
    if (path.isEmpty())
    {
        return false;
    }
    QDir dir(path);
    if (!dir.exists())
    {
        return true;
    }
    dir.setFilter(QDir::AllEntries | QDir::NoDotAndDotDot); //设置过滤
    QFileInfoList fileList = dir.entryInfoList(); // 获取所有的文件信息
    foreach (QFileInfo file, fileList)  //遍历文件信息
    {
        if (file.isFile())  // 是文件,删除
        {
            file.dir().remove(file.fileName());
        }
        else   // 递归删除
        {
            DelDir(file.absoluteFilePath());
        }
    }
    qDebug() << "删除临时文件夹成功";
    return dir.rmdir(dir.absolutePath()); // 删除文件夹
}

//下载文件
void musicwin::on_downloadBtn_clicked()
{
    NetWork *w = NetWork::getNet();
    QByteArray rec = w->socket->readAll();
    //下载前把多媒体关闭
    this->mediaPlayer->stop();
    QString filePath;
    //获取保存到的地址
    filePath = QFileDialog::getSaveFileName(this, "歌曲下载到", ".", "MP3(*.mp3)");
    if (filePath.isNull() == true)
    {
        return;
    }
    else
    {
        QTextCodec *code = QTextCodec::codecForName("GB2312");
        std::string name = code->fromUnicode(filePath).data();
        FILE *saveFile = fopen(name.c_str(), "ab+");
        if (saveFile != NULL)
        {
            //UTF-8 GBK类型转换
            this->musicPath = this->dirName + "/" + this->ui->searchEdit->text() + ".mp3";
            QTextCodec *code = QTextCodec::codecForName("GB2312");
            std::string musicName = code->fromUnicode(this->musicPath).data();
            FILE *musicFile = fopen(musicName.c_str(), "rb");
            if (musicFile == NULL)
            {
                qDebug() << "打开文件失败";
                return;
            }
            fseek(musicFile, 0, SEEK_SET);
            char buf[1000] = {'\0'};
            while (!feof(musicFile))
            {
                memset(buf, '\0', sizeof(buf));
                fread(buf, 1, sizeof(buf), musicFile);
                fwrite(buf, 1, sizeof(buf), saveFile);
            }
            fclose(musicFile);
        }
        fclose(saveFile);
    }
    this->ui->searchEdit->clear();
    this->ui->listWidget->clear();
    QMessageBox::information(this, "提示框", "开始播放下载好的歌曲");
    //此时歌曲播放
    //播放音乐
    this->mediaPlayer->setMedia(QUrl(filePath));
    //将第一首歌曲加入播放器中
    this->mediaPlayer->setMedia(QUrl(this->musicPath));
    //滚动显示歌曲名称
    QFileInfo fileInfo(filePath);
    this->musicName = fileInfo.baseName();
    //加入列表显示
    this->ui->listWidget->addItem(this->musicName);
    //显示正在播放的歌曲
    this->ui->listWidget->setCurrentRow(0);
    this->name = this->musicName + "   ";
    this->ui->label_2->setText(this->name);
    //开始播放
    this->mediaPlayer->play();
    this->timer->start(1000);
    //播放开始的时候将播放的按钮由播放设置为暂停
    this->ui->pushButton_play->setIcon(this->style()->standardIcon(QStyle::SP_MediaPause));
}
//将这个歌曲收藏到歌单里
void musicwin::on_collectBtn_clicked()
{
    //断开连接
    NetWork *w = NetWork::getNet();
    //拼接字符串
    char str[100] = {'\0'};
    QByteArray musicName = this->ui->searchEdit->text().toUtf8();
    sprintf(str, "Collect#%s", musicName.data());
    qDebug() << str;
    //有写数据的时候,会发射一个readyRead的信号
    connect(w->socket, SIGNAL(readyRead()), this, SLOT(ensureCollect()));
    //发送信息
    w->socket->write(str);
}
//确保是否加入收藏歌单内
void musicwin::ensureCollect()
{
    NetWork *w = NetWork::getNet();
    disconnect(w->socket, SIGNAL(readyRead()), this, SLOT(showMyMusic()));
    QByteArray str = w->socket->read(50);
    if (QString(str) == "1")
    {
        QMessageBox::information(this, "提示框", "收藏歌曲成功");
    }
    else
    {
        QMessageBox::warning(this, "提示框", "收藏歌曲失败");
    }
    //用完之后断开连接
    disconnect(w->socket, SIGNAL(readyRead()), this, SLOT(ensureCollect()));
}
//显示该用户的歌单
void musicwin::on_showBtn_clicked()
{
    //显示列表前清空列表框
    this->ui->listWidget->clear();
    NetWork *w = NetWork::getNet();
    //拼接字符串
    char str[100] = {'\0'};
    strcpy(str, "Show");
    qDebug() << str;
    //有写数据的时候,会发射一个readyRead的信号
    connect(w->socket, SIGNAL(readyRead()), this, SLOT(showMyMusic()));
    //发送信息
    w->socket->write(str);
}
//从服务器接收自己的歌单显示在列表框内
void musicwin::showMyMusic()
{
    NetWork *w = NetWork::getNet();
    if (this->times == 0) // 判断第一次歌单是否存在
    {
        QByteArray str = w->socket->read(50);
        this->exist = QString(str).toInt();
        this->times = 1;
    }
    else if (this->exist == 0 && this->times == 1) // 第二次如果有数据接收数据
    {
        QByteArray recv = w->socket->readAll();
        QString str = QString(recv);
        //得到了发送来的歌单的数量
        int number = str.split("#").at(1).toInt();
        //第三个开始为歌曲名字 i从2开始 所以循环歌曲数量number+2次
        for (int i = 2; i <= (number + 2); i++)
        {
            this->ui->listWidget->addItem(str.split("#").at(i));
        }
        this->times = 0;
        disconnect(w->socket, SIGNAL(readyRead()), this, SLOT(showMyMusic()));
    }
    else if (this->exist == 1)
    {
        QMessageBox::warning(this, "提示框", "您尚未收藏任何歌曲");
    }
}

        

 

 

 

                                   

 

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
课程的背景 Qt是一个1991年由奇趣科技开发的跨平台C++图形用户界面应用程序开发框架。它既可以开发GUI程式,也可用于开发非GUI程式,比如控制台 工具和服务器Qt是面向对象的框架,使用特殊的代码生成扩展(称为元对象编译器(Meta Object Compiler, moc))以及一些宏,易于扩展,允许 组件编程。2008年,奇趣科技被诺基亚公司收购,QT也因此成为诺基亚旗下的编程语言工具。2012年,Qt被Digia收购。 1.2、课程内容简介 该课程主要分为三个部分: 第一部分:从QT的基础理论知识入门 第二部分:通过QT媒体播放器项目实战训练巩固 第三部分:讲解QT系统移植 1.3、课程大纲 第一讲:QT简介、课程介绍、windows下QT开发环境搭建 第二讲:LinuxQT开发环境搭建1:VMWare安装及使用Linux安装及使用 第三讲:LinuxQT开发环境搭建2:QT X11编译、安装、使用 第四讲:LinuxQT开发环境搭建3:QTEmbedded交叉编译 第五讲:LinuxC++快速串讲1:类与对象 第六讲:LinuxC++快速串讲2:继承与多态 第七讲:QT基本图形组件 第八讲:QT信号和槽 第九讲:纯代码打造QT界面 第十讲:QT消息框和对话框 第十一讲:QT菜单 第十二讲:QT工具栏和状态栏 第十三讲:PMP媒体播放器项目实战1:需求分析与关键技术 第十四讲:PMP媒体播放器项目实战2:音频播放 第十五讲:PMP媒体播放器项目实战3:音乐切换 第十六讲:PMP媒体播放器项目实战4:添加和删除播放列表 第十七讲:PMP媒体播放器项目实战5:音量控制和播放方式 第十八讲:系统移植1:系统移植概述及UBoot移植 第十九讲:系统移植2:内核和根文件系统移植 第二十讲:系统移植3:Madplay移植和QT移植 第二十一讲:PMP项目移植与远程视频监控系统 第二十二讲:项目完善:视频播放和系统设置

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值