基于QMediaPlayer的简易视频播放器
- 1、创建基本布局
- 2、QMediaPlayer的基本使用
- 3、结合QSlider实现播放进度控制和音量控制
- 4、重载QSlider鼠标响应事件,实现单击跳转至任意位置
3、结合QSlider实现播放进度控制和音量控制
3.1 进度控制
QSlider类继承自QAbstractSlider类,可以参考 [ 官方文档 ]
其自带的信号如下:
Signal | Description |
---|---|
valueChanged() | 当进度值改变时触发 |
sliderPressed() | 当用户按下滑块时触发 |
sliderMoved() | 当用户拖动滑块时触发 |
sliderMoved() | 当用户释放滑块时触发 |
对于播放器来说,其进度条应该有两种控制方式,一是拖动,二是点击。
其中我们需要用到sliderMoved()和sliderReleased()两种信号来实现拖动功能,
对于点击,QSlider的mousePressEvent()默认的方式是,点击之后跳跃一定的固定距离,无法实现“指哪打哪”,因此我们需要对mousePressEvent()进行重写。具体方法将在下一篇文章中介绍。
首先在ui载入时将Slider禁用,等到文件载入时才启用。然后连接三组信号槽,第一组是由重载的mousePressEvent事件发送的,为避免混淆换了个costomSliderClicked的名字。其余两组是QSlider自带的sliderMoved和sliderReleased信号。
MediaPlayer::MediaPlayer(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MediaPlayer)
{
ui->setupUi(this);
ui->pushButton_play_and_pause->setEnabled(false);
ui->pushButton_volume->setEnabled(false);
ui->slider_progress->setEnabled(false);
connect(ui->slider_progress,&CustomSlider::costomSliderClicked,this,&MediaPlayer::slider_progress_clicked);
connect(ui->slider_progress,&CustomSlider::sliderMoved,this,&MediaPlayer::slider_progress_moved);
connect(ui->slider_progress,&CustomSlider::sliderReleased,this,&MediaPlayer::slider_progress_released);
}
首先我们需要配合定时器QTimer实现Slider随播放进度而移动。
之所以选择QTimer,而不是player的positionChanged信号来驱动,是因为positionChange和后面要用的QSlider两个信号槽互相修改,容易出现冲突。
添加QTimer头文件,并定义全局变量
#include <QTimer>
//与Slider有关的播放控制变量
QTimer * timer;
int maxValue = 1000;//设置进度条的最大值
在on_pushButton_open_file_clicked槽函数中添加Slider和Timer的相关代码,并将timer连接至onTimerOut槽函数:
void MediaPlayer::on_pushButton_open_file_clicked()
{
//前面部分代码与第2篇中相同//
//启用slider并设置范围
ui->slider_progress->setEnabled(true);
ui->slider_progress->setRange(0,maxValue);
timer = new QTimer();
timer->setInterval(1000);
timer->start();
//将timer连接至onTimerOut槽函数
connect(timer, SIGNAL(timeout()), this, SLOT(onTimerOut()));
}
添加定时器的槽函数onTimerOut(),其原理就是根据一定的间隔(本例中为1000ms)刷新Slider的值,这个值是根据播放器player的position(当前位置)和duration(总时长)计算出来的:
void MediaPlayer::onTimerOut()
{
ui->slider_progress->setValue(player->position()*maxValue/player->duration());
}
到这里就实现了Slider随进度移动的功能,接下来添加控制代码。
三个槽函数分别对应单击、拖动和释放。在拖动过程中,可以先暂停计时器,等用户拖动完成释放之后,再重启定时器。这样防止用户在拖动过程中滑块依然按照定时器触发进行移动,瞎跳,闹心。
void MediaPlayer::slider_progress_clicked()
{
player->setPosition(ui->slider_progress->value()*player->duration()/maxValue);
}
void MediaPlayer::slider_progress_moved()
{
//暂时停止计时器,在用户拖动过程中不修改slider的值
timer->stop();
player->setPosition(ui->slider_progress->value()*player->duration()/maxValue);
}
void MediaPlayer::slider_progress_released()
{
//用户释放滑块后,重启定时器
timer->start();
}
3.2 音量控制
音量控制的方法与进度控制非常相似,可以直接使用重载后的CustomSlider类。这里我们不在Designer中拖入控件,而是通过手动实现的方式来添加音量控制的Slider。
首先在mediaplayer.cpp的构造函数中继续添加初始化内容
MediaPlayer::MediaPlayer(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MediaPlayer)
{
/*与上述相同*/
/*
……
*/
//手动设置slider_volume 包括初始化 方向 禁用,以及槽函数
slider_volume = new CustomSlider(this);
slider_volume->setOrientation(Qt::Vertical);
slider_volume->setEnabled(false);
slider_volume->hide();
//由于不涉及到slider值的刷新,因此只需对move和自定义click两个信号进行处理,并且可以共用一个槽函数
connect(slider_volume,&CustomSlider::costomSliderClicked,this,&MediaPlayer::slider_volume_changed);
connect(slider_volume,&CustomSlider::sliderMoved,this,&MediaPlayer::slider_volume_changed);
}
槽函数
//音量控制Slider的槽函数
void MediaPlayer::slider_volume_changed()
{
player->setVolume(slider_volume->value());
}
音量控制按钮的槽函数,通过hide()和show()方法,实现音量控制Slider的唤出和收起
bool state_slider_volume = false;
void MediaPlayer::on_pushButton_volume_clicked()
{
if(state_slider_volume)
{
slider_volume->hide();
}
else
{
slider_volume->setValue(player->volume());
//计算位置,使其位于音量控制按钮的上方
slider_volume->setGeometry(QRect(ui->pushButton_volume->pos().rx()+0.5*ui->pushButton_volume->width()-15, ui->pushButton_volume->y()-100 , 30, 102));
slider_volume->show();
}
state_slider_volume = !state_slider_volume;
}
其效果如图
到这里,QSlider的移动与控制功能就已经完成了,但是实际上我们需要重载QSlider的mousePressEvent以实现指哪打哪的效果,因此需要继承一个新类CustomSlider,详情见第4篇
[ 重载QSlider鼠标响应事件,实现单击跳转至任意位置]