获取本地 qt_用QT实现视频/音乐播放组件
前言
我已經有四五天沒有發布文章了,趁著這個周末有空,就又開始構思我們自己的QT組件庫中的新組件,思考還有哪些有用、有趣、值得研究學習并構建實現的組件,于是又有了兩個新的目標,即多媒體播放組件和地圖組件。之所以準備實現這兩個小組件,是因為現在流行的很多軟件應用中幾乎都能用得到音頻視頻播放和地圖導航或定位功能。所以我們在自己的軟件開發中如果也遇到類似的需求,能有一個使用方便、快捷靈活的多媒體或地圖組件,肯定能夠節省我們很多的工作量和精力,QT雖然有相關的類但是沒有相關的組件,如是我就開始了自己的實現。
功能展示
今天先跟大家分享一下我自己實現的多媒體播放組件,使用該組件可以很方便的用來播放音樂和視頻。而且所有功能完全是基于QT自帶的QMediaPlayer類和QVideoWidget類進行實現,沒有使用任何第三方庫,所以上手也比較容易。目前已實現的基本功能有:
- 音樂/視頻播放、暫停功能
- 時長和進度顯示
- 音量調節和靜音功能
- 播放進度調整,支持時間軸點選、拖拉和鍵盤控制
- 全屏
因為錄制的gif沒有聲音,所以我只展示視頻播放功能,具體實現效果如下方動圖所示:
播放、暫停功能,點擊按鈕或視頻窗口都能實現該功能:
進度調節和音量調節:
靜音:
全屏:
實現方法
1、怎么使用QMediaPlayer類播放音樂和視頻?
播放音樂只需要設置好源即可,源既可以是本地路徑也可以是網址,如果播放使用本地文件的話,需要使用
QUrl::fromLocalFile函數,方法如下:
m_pPlayer = new QMediaPlayer;m_pPlayer->setMedia(QMediaContent(QUrl::fromLocalFile(strPath)));m_pPlayer->play();播放視頻的話還需要設置視頻輸出位置,所以QMediaPlayer通常需要連接一個QVideoWidget來進行視頻的播放,方法如下:
m_pPlayer = new QMediaPlayer;m_pVideoWidget = new QVideoWidget;m_pPlayer->setMedia(QMediaContent(QUrl::fromLocalFile(strPath)));m_pPlayer->setVideoOutput(m_pVideoWidget);m_pVideoWidget->show();2、怎么顯示視頻總時長和當前播放進度?
總時長可以通過m_pPlayer->duration()獲取,當前播放進度可以通過m_pPlayer->position()獲取,這兩個函數返回的都是毫秒數,我們只需要將該毫秒數轉換為時間并顯示到標簽上即可,我為了這兩個值能夠與時間軸對應起來,所以我都是先轉換成秒,然后再對秒進行處理:
//將秒數轉換為HH:mm::ss格式QString MediaPlayer::changeSecondsToStr(int nMesc){ m_nHour = nSeconds / 3600; nSeconds %= 3600; m_nMinute = nSeconds / 60; nSeconds %= 60; m_nSecond = nSeconds; return QString("%1:%2:%3").arg(m_nHour, 2, 10, QLatin1Char('0')).arg(m_nMinute, 2, 10, QLatin1Char('0')).arg(m_nSecond, 2, 10, QLatin1Char('0'));}為了能夠實時更新當前的播放進度,我設置了一個定時器,每50ms檢查一次當前秒數是否變化并對界面進行刷新:
//定時器超時處理void MediaPlayer::onTimerOut(){ if (m_pSlider->sliderPosition() != m_nLastPosition) { //之所以會出現這種情況,是因為觸發了鍵盤事件,比如用戶按下了方向鍵、PgUp、PgDn、Home、End m_nLastPosition = m_pSlider->sliderPosition(); m_pSlider->setValue(m_nLastPosition); m_pPlayer->setPosition(m_nLastPosition * 1000); setPlayTime(m_nLastPosition); return; } int nCurPosition = m_pPlayer->position() / 1000; if (m_nLastPosition != nCurPosition) { m_nLastPosition = nCurPosition; //檢查是否播放完畢 if (nCurPosition >= m_pPlayer->duration() / 1000) play(); m_pSlider->setValue(nCurPosition); setPlayTime(nCurPosition); }}3、如何使用QSlider對視頻進行進行展示和控制?
展示功能是很好實現的,只需要設置好QSlider的范圍并在定時器中setValue即可,QSlider本身也支持拖動控制,但是當我自定義了QSlider上滑塊的樣式后,發現拖動滑塊不是很靈敏且經常無法選中滑塊,且QSlider本身并不支持點擊改變當前值,因此我對QSlider添加了事件過濾器,并自己處理了它的鼠標點擊事件和鼠標移動事件。
m_pSlider = new QSlider(Qt::Horizontal, this); m_pSlider->setObjectName("m_pSlider"); m_pSlider->setCursor(Qt::PointingHandCursor); m_pSlider->setSingleStep(1); m_pSlider->setPageStep(10); m_pSlider->installEventFilter(this); m_pSlider->setEnabled(false);bool MediaPlayer::eventFilter(QObject *watched, QEvent *event){ //進度滑動條 if(watched == m_pSlider) { if (event->type() == QEvent::MouseButtonPress) { QMouseEvent *mouseEvent = static_cast(event); if (mouseEvent->button() == Qt::LeftButton)//判斷左鍵 { QSlider* pSlider = (QSlider*)watched; int dur = pSlider->maximum() - pSlider->minimum(); int pos = pSlider->minimum() + dur * ((double)mouseEvent->x() / pSlider->width()); if (pos != pSlider->sliderPosition()) { //if (pSlider == m_pSlider) { if (m_pSlider->isEnabled()) { m_pSlider->setValue(pos); onSliderPressed(); onSliderMoved(pos); onSliderReleased(); return true; } } } } } else if (event->type() == QEvent::MouseMove) { QMouseEvent *mouseEvent = static_cast(event); //if (mouseEvent->button() == Qt::LeftButton)//判斷左鍵 { QSlider* pSlider = (QSlider*)watched; int dur = pSlider->maximum() - pSlider->minimum(); int pos = pSlider->minimum() + dur * ((double)mouseEvent->x() / pSlider->width()); //防止超出范圍 if (pos > pSlider->maximum()) pos = pSlider->maximum(); if (pos < pSlider->minimum()) pos = pSlider->minimum(); if (pos != pSlider->sliderPosition()) { //if (pSlider == m_pSlider) { if (m_pSlider->isEnabled()) { m_pSlider->setValue(pos); onSliderPressed(); onSliderMoved(pos); onSliderReleased(); return true; } } } } } } return QObject::eventFilter(watched, event);}如果在視頻播放過程中改變進度的話,定時器還在運行,可能也會同時修改視頻的進度,所以在用m_pSlider改變播放進度時,需要先停止視頻播放和定時器,這個操作我們通過管理QSlider的鼠標按下響應、鼠標移動響應和鼠標釋放響應進行處理。當鼠標按下時停止視頻播放和定時器,鼠標移動時修改視頻進度,鼠標釋放時恢復視頻播放和重啟定時器。
connect(m_pSlider, SIGNAL(sliderPressed()), this, SLOT(onSliderPressed()));connect(m_pSlider, SIGNAL(sliderMoved(int)), this, SLOT(onSliderMoved(int)));connect(m_pSlider, SIGNAL(sliderReleased()), this, SLOT(onSliderReleased()));//滑動條鼠標點擊響應void MediaPlayer::onSliderPressed(){ m_bIsLastPlay = m_bIsPlay;}//滑動條滑動響應void MediaPlayer::onSliderMoved(int nPosition){ Q_UNUSED(nPosition); //在拖動過程中暫停播放 if (m_bIsPlay) play(); if (m_nLastPosition != nPosition) { m_nLastPosition = nPosition; m_pSlider->setValue(m_nLastPosition); m_pPlayer->setPosition(m_nLastPosition * 1000); setPlayTime(m_nLastPosition); }}//滑動條鼠標釋放響應void MediaPlayer::onSliderReleased(){ if (m_bIsLastPlay) play();}4、如何實現音量控制和音量控制窗口的自動顯示和隱藏?
音量修改也是使用滑動條進行控制,實現方法和改變播放進度類似,就不再細說。這里只說一下怎么控制音量窗口的自動出現和隱藏。當鼠標移動到音量按鈕上方時,音量窗口自動顯示,當鼠標移動到音量窗口上方時,音量窗口一直保持顯示狀態,當鼠標從音量窗口移出1s以后,音量窗口自動隱藏。了解這個過程以后,其實不難發現,還是需要對鼠標事件進行過濾和自定義處理。至于怎么使窗口延遲1s后隱藏,使用QTimer::singleShot進行單次觸發最為方便合適。
bool MediaPlayer::eventFilter(QObject *watched, QEvent *event){ if (watched == m_pVolumeButton) //音量鍵 { if (event->type() == QEvent::Enter) { changeVolume(m_pPlayer->volume()); m_pVolumeSlider->setValue(m_pPlayer->volume()); //計算位置,使其位于音量控制按鈕的上方 m_pVolumeWidget->setGeometry(QRect(m_pVolumeButton->pos().rx()+0.5*m_pVolumeButton->width()-m_pVolumeWidget->width()/2, m_pControlWidget->y()-110 , m_pVolumeWidget->width(), 100)); m_pVolumeWidget->show(); m_bVolume = true; } if (event->type() == QEvent::Leave) { m_bVolume = false; QTimer::singleShot(1000, this, SLOT(hideSlider())); } } else if (watched == m_pVolumeWidget) //音量窗口 { if (event->type() == QEvent::Enter) m_bVolume = true; else if(event->type() == QEvent::Leave) { m_bVolume = false; QTimer::singleShot(1000, this, SLOT(hideSlider())); } } return QObject::eventFilter(watched, event);}5、如何實現實現靜音和全屏顯示?
當我們點擊音量按鈕的時候進行打開靜音或關閉靜音操作,當然靜音時手動的設置音量為0也無可厚非,但是QMediaPlayer中也提高了相關接口,使用方法如下:
//打開或關閉靜音void MediaPlayer::openOrCloseMute(){ if (m_pPlayer->isMuted()) m_pVolumeButton->setIcon(QIcon(":/Images/MediaPlayer_Icon/sound.png")); else m_pVolumeButton->setIcon(QIcon(":/Images/MediaPlayer_Icon/mute.png")); m_pPlayer->setMuted(!m_pPlayer->isMuted());全屏方法也是調用接口,直接上代碼:
//打開或關閉全屏顯示void MediaPlayer::openOrCloseFullScreen(){ if (this->isFullScreen()) { m_pFullScreenButton->setIcon(QIcon(":/Images/MediaPlayer_Icon/showMax.png")); m_pFullScreenButton->setToolTip("進入全屏"); this->showNormal(); } else { m_pFullScreenButton->setIcon(QIcon(":/Images/MediaPlayer_Icon/showNormal.png")); m_pFullScreenButton->setToolTip("退出全屏"); this->showFullScreen(); }}總結
其實整個實現過程也很簡單,主要是QSlider的使用和對鼠標移動事件的處理,該組件的下方控制窗口也可以實現自動隱藏,實現方法和音量窗口類似。還可以集成之前我們自己做的彈幕組件,從而支持發送彈幕功能,由于時間關系,我就沒有實現。該組件的使用方法也非常方便:
MediaPlayer *pMediaPlayer = new MediaPlayer;pMediaPlayer->show();//pMediaPlayer->playMusic("D:/CloudMusic/1.mp3"); //播放音樂pMediaPlayer->playVideo("C:/Users/金/Desktop/2.mp4"); //播放視頻源碼大概有500行左右,這里就不再貼出來了,否則篇幅太長,主要功能實現,上面也都放了源碼,如果有需要也可以評論留言,后期也會統一上傳github。
總結
以上是生活随笔為你收集整理的获取本地 qt_用QT实现视频/音乐播放组件的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 武林外史java游戏,武林外史_网络游戏
- 下一篇: matlab 读取excel一列,读取e