赞
踩
可以显示jpg、jpeg、png、bmp。可以从电脑上拖动图到窗口并显示出来或者打开文件选择,定时滚动图片
重载实现dragEnterEvent(拖拽)、dropEvent(拖拽放下)、resizeEvent(窗口大小改变)
解决:
[QWidget::paintEngine: Should no longer be called QPainter::begin: Paint device returned engine == 0, type: 1]
需要在哪个控件上绘制,就要在哪个控件类中重写 paintEvent() ,所以本项目 需要使用自定义的MyQLabel继承QLabel
没有透明过渡动画版本Qt图片定时滚动播放器,没有透明过渡动画
QT += core gui greaterThan(QT_MAJOR_VERSION, 4): QT += widgets CONFIG += c++11 # You can make your code fail to compile if it uses deprecated APIs. # In order to do so, uncomment the following line. #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 SOURCES += \ main.cpp \ myqlabel.cpp \ pictureplay.cpp HEADERS += \ myqlabel.h \ pictureplay.h FORMS += \ pictureplay.ui # Default rules for deployment. qnx: target.path = /tmp/$${TARGET}/bin else: unix:!android: target.path = /opt/$${TARGET}/bin !isEmpty(target.path): INSTALLS += target RESOURCES += \ res.qrc
#include "pictureplay.h" #include <QApplication> #include<QFile> int main(int argc, char *argv[]) { QApplication a(argc, argv); // 加载样式文件 QFile file(":/style.qss"); /*判断文件是否存在*/ if(file.exists()) { file.open(QFile::ReadOnly);// 以只读的方式打开 //QString styleSheet=QLatin1String(file.readAll());// 以Latin-1编码的字符串的方式保存读出的结果 QString styleSheet=QString(file.readAll());// 以默认编码的字符串的方式保存读出的结果 qApp->setStyleSheet(styleSheet);// 设置全局样式 file.close();// 关闭文件 } //在窗口显示前判断使用 PicturePlay w; w.show(); return a.exec(); }
#ifndef MYQLABEL_H #define MYQLABEL_H #include <QWidget> #include <QLabel> #include <QPainter> #include <QPropertyAnimation> class MyQLabel : public QLabel { Q_OBJECT public: explicit MyQLabel(QWidget *parent = nullptr); void paintEvent(QPaintEvent *event)override;// 绘图事件; // 图片切换动画类; QPropertyAnimation* m_opacityAnimation; QPixmap currentPixmap; QPixmap nextPixmap; bool paintEvent_Flag; signals: }; #endif // MYQLABEL_H
#include "myqlabel.h" #include<QVariant> #include<QDebug> MyQLabel::MyQLabel(QWidget *parent) : QLabel(parent) { this->setProperty("ImageOpacity",1.0); this->paintEvent_Flag=false; // 动画切换类; m_opacityAnimation = new QPropertyAnimation(this, "ImageOpacity"); // 这里要设置的动画时间小于图片切换时间; m_opacityAnimation->setDuration(1500); // 设置ImageOpacity属性值的变化范围; m_opacityAnimation->setStartValue(1.0); m_opacityAnimation->setEndValue(0.0); // 透明度变化及时更新绘图; connect(m_opacityAnimation, SIGNAL(valueChanged(const QVariant&)),this, SLOT(update())); m_opacityAnimation->stop(); } int i=0; void MyQLabel::paintEvent(QPaintEvent *event) { if(!currentPixmap.isNull()&&!nextPixmap.isNull()&&paintEvent_Flag) { this->clear(); QPainter painter(this); QRect imageRect = this->rect(); float imageOpacity = this->property("ImageOpacity").toFloat(); //qDebug()<<"i=["<<i++<<"]imageOpacity="<<imageOpacity; painter.setOpacity(1); painter.drawPixmap(imageRect, nextPixmap.scaled(imageRect.size())); painter.setOpacity(imageOpacity); painter.drawPixmap(imageRect, currentPixmap.scaled(imageRect.size()));// 透明度减到0 } QLabel::paintEvent(event); }
#ifndef PICTUREPLAY_H #define PICTUREPLAY_H #include <QWidget> #include <QFile> #include <QDir> #include <QTimer> #include <QThread> #include <QFileDialog> #include <QScrollArea> #include <QPropertyAnimation> QT_BEGIN_NAMESPACE namespace Ui { class PicturePlay; } QT_END_NAMESPACE class PicturePlay : public QWidget { Q_OBJECT public: PicturePlay(QWidget *parent = nullptr); ~PicturePlay(); private slots: void myautoPhoto(); //自动播放函数 void showDinamicPhoto(QString path);//动态图播放(格式为gif) void on_pathBtn_clicked();//浏览:打开目录 void on_autoPhoto_clicked(bool checked);//自动播放选择 void on_photoList_clicked(const QModelIndex &index);//单击播放图片 void my_currentRowChanged(int Row);// // 当前项变化 void on_cleanBtn_clicked();//清除 private: QString Dir;//打开文件的路径 QString tempDir; //照片的绝地路径 QVector<QString> photoPath;//存放照片相对路径的容器 QTimer *mtime; //定时器 QString delayTime; //延时间隔 bool autoFlag; //判断是否进入的自动播放格式 int num; // 当前显示图片index; // 如果文件的后缀名是jpg、jpeg、bmp或png,则接受拖放事件,否则忽略拖放事件 QStringList acceptedFileTypes; void dragEnterEvent(QDragEnterEvent *event)override;//拖进事件 void dropEvent(QDropEvent *event)override;// 拖进放下事件 void resizeEvent(QResizeEvent *event)override;//用于在窗口大小改变时处理事件 void paintEvent(QPaintEvent *event)override;// 绘图事件; // 切换图片; QPixmap pixmap; // QPixmap currentPixmap; // QPixmap nextPixmap; // 用来做图片切换滑动效果,目前以透明度作为切换效果; QScrollArea* m_imagePlayWidget; // // 图片切换动画类; // QPropertyAnimation* m_opacityAnimation; private: Ui::PicturePlay *ui; }; #endif // PICTUREPLAY_H
#include "pictureplay.h" #include "ui_pictureplay.h" #include<QDebug> #include<QMessageBox> #include<QMovie> #include <QDragEnterEvent> #include <QDropEvent> #include <QMimeData> #include <QPainter> PicturePlay::PicturePlay(QWidget *parent) : QWidget(parent) , ui(new Ui::PicturePlay) { ui->setupUi(this); this->setWindowTitle("图片播放器"); this->setWindowIcon(QIcon(":/ImageEye.jpg")); this->setAcceptDrops(true);//设置允许向窗口拖入图片 this->setMinimumSize(QSize(400,300));// 设置最小值 ui->photoShow->setAlignment(Qt::AlignCenter); //居中显示 //自适应的label+pixmap充满窗口后,无法缩小只能放大 ui->photoShow->setSizePolicy(QSizePolicy::Ignored,QSizePolicy::Ignored);// Ignored忽略 // 内容是否自动缩放,参数true自动缩放 ui->photoShow->setScaledContents(true);//显示图片的全部 // 设置拉伸因子(默认缩到最小时失效:一样大小) ui->horizontalLayout_2->setStretch(1,3); // 设置水平布局控件到边框距离(左,上,右,下) ui->horizontalLayout_2->setContentsMargins(5,0,5,0); //设置窗口布局,(此时控件会随窗口缩放) this->setLayout(ui->horizontalLayout_2); ui->photoPath->setFocusPolicy(Qt::NoFocus);//无法获得焦点,自然无法输入,其他文本控件类似 ui->photoPath->setPlaceholderText("绝对路径"); ui->delayEdit->setPlaceholderText("秒"); //不显示行向滚动条,子项文本过长自动显示... ui->photoList->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); num=0; //照片张数 delayTime.clear(); //延时间隔 mtime = new QTimer(this); //连接自动播放槽函数 connect(mtime,SIGNAL(timeout()),this,SLOT(myautoPhoto())); connect(ui->photoList,SIGNAL(currentRowChanged(int)),this,SLOT(my_currentRowChanged(int))); // 如果文件的后缀名是jpg、jpeg、bmp或png,则接受拖放事件,否则忽略拖放事件 acceptedFileTypes.append("jpg"); acceptedFileTypes.append("jpeg"); acceptedFileTypes.append("bmp"); acceptedFileTypes.append("png"); acceptedFileTypes.append("gif"); } PicturePlay::~PicturePlay() { delete ui; } //自动播放函数 void PicturePlay::myautoPhoto() { tempDir.clear(); tempDir=photoPath.at(num); //从容器中找到要播放的照片的相对路径 ui->photoList->setCurrentRow(num);// QListWidget项跳动 if(tempDir.endsWith(".gif") || tempDir.endsWith(".Gif")) { showDinamicPhoto(tempDir); num++; } else if(!(tempDir.endsWith(".gif") || tempDir.endsWith(".Gif"))) { ui->photoShow->paintEvent_Flag=true; ui->photoShow->currentPixmap=pixmap;// 1.先赋值 pixmap.load(tempDir);// 2.再更新全局图片 // 先设置下一个的图片; ui->photoShow->nextPixmap=pixmap;//3.最后需要立即显示的图片 // 动画类重新开始; ui->photoShow->m_opacityAnimation->start(); //判断自动播放的时候是否播放到了最后一张图片,如果是则停止自动播放 if(num == (photoPath.count()-1)) { //qDebug()<<num; if(ui->loopPlayback->checkState()==Qt::Checked)//循环重放 { num = -1;// 下面num++,为了循环重放回到第一张图片 qDebug()<<num; } else { mtime->stop(); num = 0; if(autoFlag)//选中自动播放的情况 { autoFlag = false; } //qDebug()<<num; ui->autoPhoto->setCheckState(Qt::Unchecked);//把自动播放按钮置于没有选择的状态 } } if(autoFlag) { num++; } } } //动态图播放(格式为gif) void PicturePlay::showDinamicPhoto(QString path) { ui->photoShow->clear(); ui->photoShow->paintEvent_Flag=false; QMovie *movie = new QMovie(path); // path图片路径 movie->start(); //开始播放动态图 ui->photoShow->setMovie(movie); //将图片设置为为动态 ui->photoShow->setScaledContents(true); //尽可能完整的播放整张动图 ,此处要设置为true } //浏览:打开目录 void PicturePlay::on_pathBtn_clicked() { Dir = QFileDialog::getExistingDirectory(this);//获取本文件所在的具体路径 //qDebug()<<"路径:"<<Dir; ui->photoPath->setText(Dir);//显示打开的文件的具体路径 QDir dir(Dir); QStringList file; QFileInfoList fileList = dir.entryInfoList(file,QDir::Files); //获取目录下的文件 QString fileDir; //保存图片所在的路径 //列出目录下的文件 for(int i=0;i<fileList.count();i++) { if(i==50) { break; } QFileInfo info = fileList.at(i); fileDir.clear(); if(info.fileName() == "." || info.fileName() == "..") //跳过这两个目录 { continue; } // 检查文件的后缀名是否在接受的文件类型列表中;(获取文件的后缀名,并将其转换为小写字母) if(!acceptedFileTypes.contains(info.suffix().toLower())) { continue; } fileDir+=Dir + "/"; QString filename = info.fileName(); fileDir+=filename; photoPath.append(fileDir);// 把图片的路径装到容器中 QListWidgetItem *item = new QListWidgetItem(QIcon(fileDir),info.fileName());//建立文件缩小图标 item->setToolTip(info.fileName());// tip提示 item->setTextAlignment(Qt::AlignCenter);//设置item项中的文字位置 ui->photoList->addItem(item);//把图片相对路径显示到窗口中 } if(ui->photoList->count()==0) { QListWidgetItem *item = new QListWidgetItem("无合适图片"); item->setTextAlignment(Qt::AlignCenter);//设置item项中的文字位置 ui->photoList->addItem(item);//把图片相对路径显示到窗口中 } } //自动播放选择 void PicturePlay::on_autoPhoto_clicked(bool checked) { if(ui->delayEdit->text().isEmpty()) { QMessageBox::warning(this,"提示","请输入需要间隔的播放时间(秒)"); //把按钮重新置于没有被选中的状态;不要用setCheckable()函数[不可用],很容易出错 ui->autoPhoto->setCheckState(Qt::Unchecked); return; } else if(ui->photoList->count() == 0) { QMessageBox::warning(this,"警告","还没有可以播放的图片"); ui->autoPhoto->setCheckState(Qt::Unchecked); //把按钮重新置于没有被选中的状态 return; } else if(ui->delayEdit->text().toInt()<2)// 图片切换时间大于动画时间 { QMessageBox::warning(this,"警告","请输入间隔的播放时间大于等于 2 (秒)"); ui->autoPhoto->setCheckState(Qt::Unchecked); //把按钮重新置于没有被选中的状态 return; } else if(checked) //启动定时器 { delayTime = ui->delayEdit->text(); mtime->start(delayTime.toInt()*1000);//启动定时器并设置播放时间间隔 autoFlag = true;// 选中自动播放 // 第一次:立即显示,无需等待 ui->photoList->setCurrentRow(num);// QListWidget项跳动 pixmap.load(photoPath.at(num));// 先更新全局图片 ui->photoShow->paintEvent_Flag=true; ui->photoShow->currentPixmap=ui->photoShow->nextPixmap=pixmap;//再赋值 update();// 手动刷新 } else if(!checked)//停止定时器 { mtime->stop();//停止定时器 delayTime.clear(); autoFlag = false; ui->photoShow->paintEvent_Flag=false; } } //单击播放图片 void PicturePlay::on_photoList_clicked(const QModelIndex &index) { qDebug()<<"单击播放图片"; Q_UNUSED(index);//忽略编译器发出的警告,表明变量event未使用 //如果选中了自动播放的情况下,点击列表中的内容,则停止自动播放 if(autoFlag) //选中自动播放的情况 { mtime->stop(); //把按钮重新置于没有被选中的状态;不要用setCheckable()函数[不可用],很容易出错 ui->autoPhoto->setCheckState(Qt::Unchecked); autoFlag = false; } num = ui->photoList->row(ui->photoList->currentItem()); //获取当前点击的内容的行号 //在没有选中自动播放的情况下,判断当前是否点击了最后一张照片,如果是最后一张照片,在选中自动播放的情况下让它返回到第一张照片 if(!autoFlag&&num == ui->photoList->count()) { num = 0; } tempDir.clear(); /*tempDir+=Dir+"/"; QString path = ui->photoList->currentItem()->text(); tempDir+=path*/; tempDir=photoPath.at(num); //从容器中找到要播放的照片的相对路径 //判断是否是动态图;endsWith()字符串结尾 if(tempDir.endsWith(".gif") || tempDir.endsWith(".Gif")) { showDinamicPhoto(tempDir); } else { if(pixmap.isNull()) { pixmap.load(tempDir);// 更新全局图片 ui->photoShow->currentPixmap=ui->photoShow->nextPixmap=pixmap; }else { ui->photoShow->currentPixmap=pixmap; pixmap.load(tempDir);// 更新全局图片 ui->photoShow->nextPixmap=pixmap; } ui->photoShow->paintEvent_Flag=true; // 动画类重新开始; ui->photoShow->m_opacityAnimation->start(); } } // 当前项变化 void PicturePlay::my_currentRowChanged(int Row) { qDebug()<<"当前项变化:"<<Row; } //拖进事件 void PicturePlay::dragEnterEvent(QDragEnterEvent *event) { // 用于检查拖放的数据是否包含URL,并且获取拖放事件中的URL数量==1 if(event->mimeData()->hasUrls()&&event->mimeData()->urls().count()==1) { // 获取拖放事件中的第一个URL的本地文件路径 QFileInfo file(event->mimeData()->urls().at(0).toLocalFile()); // 检查文件的后缀名是否在接受的文件类型列表中;(获取文件的后缀名,并将其转换为小写字母) if(acceptedFileTypes.contains(file.suffix().toLower())) { event->acceptProposedAction();//表明用户可以在窗口部件上拖放对象[接受拖放事件的操作] } } } // 拖进放下事件 void PicturePlay::dropEvent(QDropEvent *event) { // 获取拖放事件中的第一个URL的本地文件路径 QFileInfo file(event->mimeData()->urls().at(0).toLocalFile()); //qDebug()<<"绝对路径:"<<file.absoluteFilePath(); //从文件中加载图片,参数file.absoluteFilePath()表示包含文件名的绝对路径,load()返回一个bool值,表示是否加载成功 if(pixmap.load(file.absoluteFilePath())) { ui->photoShow->paintEvent_Flag=true; ui->photoShow->currentPixmap=ui->photoShow->nextPixmap=pixmap; update();// 手动刷新,否则鼠标拖进放下,如果鼠标不在窗口不会刷新,图片不会显示 ui->photoPath->setText(file.absolutePath());//显示打开的文件的绝对路径,这不包括文件名。 photoPath.append(file.absoluteFilePath());// 把图片的路径装到容器中 QListWidgetItem *item = new QListWidgetItem(QIcon(file.absoluteFilePath()),file.fileName());//建立文件缩小图标 item->setToolTip(file.fileName());// tip提示 item->setTextAlignment(Qt::AlignCenter);//设置item项中的文字位置 ui->photoList->addItem(item);//把图片相对路径显示到窗口中 }else { // 错误消息框 QMessageBox::critical(this,tr("Error"),tr("The image file count not be read")); } } //用于在窗口大小改变时处理事件 int j=0; void PicturePlay::resizeEvent(QResizeEvent *event) { Q_UNUSED(event);//忽略编译器发出的警告,表明变量event未使用 qDebug()<<"窗口大小改变:"<<j++; if(!pixmap.isNull()) { // 在MyQLaBel的paintEvent绘图事件,会重绘 //ui->photoShow->setPixmap(pixmap.scaled(ui->photoShow->size(),Qt::KeepAspectRatio,Qt::SmoothTransformation)); } } //绘图事件 void PicturePlay::paintEvent(QPaintEvent *event) { //QPainter painter(ui->photoShow); /*报错 QWidget::paintEngine: Should no longer be called QPainter::begin: Paint device returned engine == 0, type: 1 */ //想要在哪个控件上绘制,就要在哪个控件类中重写 paintEvent() 方法才行。 //比如想要在 QLabel 上绘图,就需要新建一个类继承于 QLabel,然后重写 paintEvent() 方法 //也就是在此文件只能用QPainter painter(this); Q_UNUSED(event);//忽略编译器发出的警告,表明变量event未使用 } // 清除 void PicturePlay::on_cleanBtn_clicked() { mtime->stop(); num = 0; if(autoFlag)//选中自动播放的情况 { autoFlag = false; } pixmap.fill(Qt::transparent);//函数用于将QPixmap对象pixmap清空,参数Qt::transparent表示填充透明色,无返回值 ui->autoPhoto->setCheckState(Qt::Unchecked);//把自动播放按钮置于没有选择的状态 ui->loopPlayback->setCheckState(Qt::Unchecked);//把循环重放钮置于没有选择的状态 photoPath.clear(); ui->photoPath->clear(); ui->photoList->clear(); ui->photoShow->clear(); ui->photoShow->nextPixmap=ui->photoShow->currentPixmap=pixmap; ui->photoShow->paintEvent_Flag=false; }
QListWidget { border:1px solid gray; /*边界线:宽度、颜色*/ /*background:gray;*/ /*表格背景色*/ color:black; /*前景色:文字颜色*/ /*margin:5px,5px,0px,50px;*/ /*上、下、左、右,间距*/ } QListWidget{ /*去掉选中时的虚线框*/ outline:0px; } QListWidget::item { padding-top:12px; padding-bottom:4px; } QListWidget::item:hover/*悬停*/ { show-decoration-selected:5; background:skyblue;/*天蓝色*/ } QListWidget::item:selected { /*border:0px;*/ background:lightgray;/*浅灰色*/ padding:0px; margin:0px; color:red; } /*上次选择后保留的状态,鼠标离开后显示*/ QListWidget::item:selected:!active { border:none;/*无边框*/ background:lightgreen;/*浅绿色*/ }
有道云:Qt图片定时滚动播放器
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。