状态切换按钮
我们之前制作过按钮类为PicButton,但是这次我们要制作另外一个按钮类,主要是实现状态切换,比如当前是播放状态,那么按钮就显示出暂停的图标,点击暂停后切换为播放的图标。同时还要支持滑动,点击,正常的三种效果。 PicStateBtn构造函数
PicStateBtn::PicStateBtn(QWidget *parent ):QPushButton (parent){
}
添加一个函数设置播放状态和暂停状态的图标
void PicStateBtn::SetIcons(const QString &normal, const QString &hover, const QString &pressed,
const QString &normal_2, const QString &hover_2, const QString &pressed_2)
{
_normal = normal;
_hover = hover;
_pressed = pressed;
_normal_2 = normal_2;
_hover_2 = hover_2;
_pressed_2 = pressed_2;
QPixmap tmpPixmap;
tmpPixmap.load(normal);
this->resize(tmpPixmap.size());
this->setIcon(tmpPixmap);
this->setIconSize(tmpPixmap.size());
_cur_state = PicBtnStateNormal;
}
normal,hover,pressed分别表示播放状态正常,悬浮,点击的效果。 _normal_2,_hover_2,_pressed_2分别表示暂停状态正常,悬浮,点击的效果。 _cur_state表示现在是上述六种状态的哪一种,具体定义在const.h文件里
enum PicBtnState {
PicBtnStateNormal = 1,
PicBtnStateHover = 2,
PicBtnStatePress = 3,
PicBtnState2Normal = 4,
PicBtnState2Hover = 5,
PicBtnState2Press = 6,
};
对应的我们实现了六种状态的加载函数
void PicStateBtn::setNormalIcon(){
qDebug()<<"setNormalIcon _normal " << _normal << endl;
QPixmap tmpPixmap;
tmpPixmap.load(_normal);
this->setIcon(tmpPixmap);
_cur_state = PicBtnStateNormal;
}
void PicStateBtn::setHoverIcon(){
qDebug()<<"setHoverIcon _hover " << _hover << endl;
QPixmap tmpPixmap;
tmpPixmap.load(_hover);
this->setIcon(tmpPixmap);
_cur_state = PicBtnStateHover;
}
void PicStateBtn::setPressIcon(){
qDebug()<<"setPressIcon _pressed " << _pressed << endl;
QPixmap tmpPixmap;
tmpPixmap.load(_pressed);
this->setIcon(tmpPixmap);
_cur_state = PicBtnStatePress;
}
void PicStateBtn::setNormal2Icon()
{
qDebug()<<"setPressIcon _normal_2 " << _normal_2 << endl;
QPixmap tmpPixmap;
tmpPixmap.load(_normal_2);
this->setIcon(tmpPixmap);
_cur_state = PicBtnState2Normal;
}
void PicStateBtn::setHover2Icon()
{
qDebug()<<"setPressIcon _hover_2 " << _hover_2 << endl;
QPixmap tmpPixmap;
tmpPixmap.load(_hover_2);
this->setIcon(tmpPixmap);
_cur_state = PicBtnState2Hover;
}
void PicStateBtn::setPress2Icon()
{
qDebug()<<"setPressIcon _pressed_2 " << _pressed_2 << endl;
QPixmap tmpPixmap;
tmpPixmap.load(_pressed_2);
this->setIcon(tmpPixmap);
_cur_state = PicBtnState2Press;
}
接下来实现鼠标滑动,点击,以及正常效果的切换,我们重写event
bool PicStateBtn::event(QEvent *event)
{
switch (event->type())
{
case QEvent::Enter:
if(_cur_state < PicBtnState2Normal){
setHoverIcon();
}else{
setHover2Icon();
}
break;
case QEvent::Leave:
if(_cur_state < PicBtnState2Normal){
setNormalIcon();
}else{
setHover2Icon();
}
break;
case QEvent::MouseButtonPress:
if(_cur_state < PicBtnState2Normal){
setPressIcon();
}else{
setPress2Icon();
}
break;
case QEvent::MouseButtonRelease:
if(_cur_state < PicBtnState2Normal){
setHover2Icon();
}else{
setHoverIcon();
}
break;
default:
break;
}
return QPushButton::event(event);
}
上述根据现在是播放状态还是暂停状态,再根据鼠标事件设置图标。 另外我们需要实现开始和暂停的切换效果,所以新增两个槽函数
void PicStateBtn::SlotStart()
{
setNormal2Icon();
}
void PicStateBtn::SlotStop()
{
setNormalIcon();
}
我们回到SlideShowDlg.ui文件,将playBtn升级为PicStateBtn。 然后在SlideShowDlg的构造函数里为按钮设置图标,并且将PicAnimationWid的SigStart和SigStop信号与之连接起来
ui->playBtn->SetIcons(":/icon/play.png",":/icon/play_hover.png",":/icon/play_press.png",
":/icon/pause.png",":/icon/pause_hover.png",":/icon/pause_press.png");
//连接动画和按钮显示状态
connect(ui->picAnimation,&PicAnimationWid::SigStart, ui->playBtn, &PicStateBtn::SlotStart);
connect(ui->picAnimation,&PicAnimationWid::SigStop, ui->playBtn, &PicStateBtn::SlotStop);
这样动画一开始按钮就被设置为暂停图标,表示动画正在运行,点击暂停图标又会切换为运行图标,表示动画已经暂停。
关闭按钮
SlideShowDlg的关闭按钮比较影响体验,我们隐藏边框上的按钮,在构造函数里添加
this->setWindowFlags(Qt::Dialog|Qt::FramelessWindowHint);
升级SlideShowDlg的ui文件中的closeBtn为PicButton,并且在构造函数里添加加载图标的逻辑和信号连接。
ui->closeBtn->SetIcons(":/icon/closeshow.png",":/icon/closeshow_hover.png",
":/icon/closeshow_press.png");
//连接关闭按钮
connect(ui->closeBtn, &QPushButton::clicked, this, &SlideShowDlg::close);
这样就能响应关闭按钮的事件了。
切换跳转
我们需要点击向前和向后按钮,实现动画图片的切换,这里先升级SlideShowDlg的ui文件中的slidenextBtn和slidpreBtn按钮为PicButton 然后在构造函数添加加载逻辑和信号连接
ui->slidpreBtn->SetIcons(":/icon/previous.png",
":/icon/previous_hover.png",
":/icon/previous_press.png");
ui->slidenextBtn->SetIcons(":/icon/next.png",
":/icon/next_hover.png",
":/icon/next_press.png");
//连接向后查看按钮
connect(ui->slidenextBtn, &QPushButton::clicked,this,&SlideShowDlg::SlotSlideNext);
//连接向前查看按钮
connect(ui->slidpreBtn, &QPushButton::clicked,this,&SlideShowDlg::SlotSlidePre);
这两个槽函数内部调用了PicAnimationWid的SlideNext和SlidePre
void SlideShowDlg::SlotSlideNext()
{
ui->picAnimation->SlideNext();
}
void SlideShowDlg::SlotSlidePre()
{
ui->picAnimation->SlidePre();
}
PicAnimationWid的两个函数分别实现图片的切换
void PicAnimationWid::SlideNext()
{
Stop();
if(!_cur_item){
return;
}
auto * cur_pro_item = dynamic_cast<ProTreeItem*>(_cur_item);
auto * next_item = cur_pro_item->GetNextItem();
if(!next_item){
return;
}
SetPixmap(next_item);
update();
}
void PicAnimationWid::SlidePre()
{
Stop();
if(!_cur_item){
return;
}
auto * cur_pro_item = dynamic_cast<ProTreeItem*>(_cur_item);
auto * pre_item = cur_pro_item->GetPreItem();
if(!pre_item){
return;
}
SetPixmap(pre_item);
update();
}
切换后动画暂停,变为显示图片的状态。 为了美观,我们完善一下qss
#preListWidget {
color:rgb(231,231,231);
background-color:rgb(46,47,48);
border: 0px;
}
#preListWidget::item:hover {
background: rgb(38, 95, 153);
}
#preListWidget::item:selected {
background: rgb(38, 95, 153);
}
#slidpreBtn,#slidenextBtn,#playBtn {
border: 0px;
}
#slideprewid {
margin-left:10px;
}
#slidenextwid{
margin-right:10px;
}
#preListWidget::item:selected:active{
border: 2px solid #FFFFFF;
}
#preListWidget::item:selected{
border: 2px solid #FFFFFF;
}
将按钮设置为无边框,然后设置了preListWidget的边框和边距等信息。
添加音乐
为了让动画播放过程中能够播放音乐,我们在mainwindow的菜单里添加音乐菜单。
//设置背景音乐动作
QAction * act_music = new QAction(QIcon(":/icon/music.png"), tr("背景音乐"),this);
act_music->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_M));
menu_set->addAction(act_music);
//设置音乐
connect(act_music, &QAction::triggered, pro_tree_widget, &ProTreeWidget::SlotSetMusic);
在打开音乐的槽函数里弹出一个文件夹对话框
void ProTreeWidget::SlotSetMusic(bool)
{
qDebug() << "SlotSetMusic" <<endl;
QFileDialog file_dialog;
file_dialog.setFileMode(QFileDialog::ExistingFiles);
file_dialog.setWindowTitle("选择导入的文件夹");
file_dialog.setDirectory(QDir::currentPath());
file_dialog.setViewMode(QFileDialog::Detail);
file_dialog.setNameFilter("(*.mp3)");
QStringList fileNames;
if (file_dialog.exec()){
fileNames = file_dialog.selectedFiles();
}
if(fileNames.length() <= 0){
return;
}
_playlist->clear();
for(auto filename : fileNames){
qDebug() << "filename is " << filename << endl;
_playlist->addMedia(QUrl::fromLocalFile(filename));
}
if(_player->state()!=QMediaPlayer::PlayingState)
{
_playlist->setCurrentIndex(0);
}
}
文件夹对话框返回选择的文件列表,我们将文件列表加入播放列表_playlist。然后通过判断_player的状态设置索引。 _player为QMediaPlayer类型,_playlist为QMediaPlaylist类型,我们需要在pro里添加multimedia才能使用。
QT += core gui multimedia
另外要在protreewidget头文件包含
#include<QtMultimedia/QMediaPlayer>
#include<QtMultimedia/QMediaPlaylist>
然后在SlideShowDlg的构造函数添加播放音乐和停止音乐的槽函数
//连接音乐启动信号
connect(ui->picAnimation, &PicAnimationWid::SigStartMusic, _protree_widget,
&ProTreeWidget::SlotStartMusic);
//连接音乐关闭信号
connect(ui->picAnimation,&PicAnimationWid::SigStopMusic, _protree_widget,
&ProTreeWidget::SlotStopMusic);
播放音乐和停止音乐逻辑很简单
void ProTreeWidget::SlotStartMusic()
{
qDebug()<< "ProTreeWidget::SlotStartMusic" << endl;
_player->play();
}
void ProTreeWidget::SlotStopMusic()
{
qDebug()<< "ProTreeWidget::SlotStopMusic" << endl;
_player->pause();
}