需求描述

在场景中实现拖动,缩放,并在场景的缩略图中显示其对应在视口中显示的矩形区域。
程序效果图如下:

开发环境:Qt 5.13.1
编译环境:MinGW64
项目结构:

直接上程序:
main.cpp

#include "dialog.h"
#include "log.hpp"
#include <QMutex>
#include <QDateTime>
#include <QFile>#include <QApplication>
void MessageTypePut(QtMsgType type, const QMessageLogContext &context, const QString &msg);
int main(int argc, char *argv[])
{#ifdef OUTPUT_LOGqInstallMessageHandler(MessageTypePut);
#endifQApplication a(argc, argv);Dialog w;w.show();return a.exec();
}void MessageTypePut(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{//    getCurrFilePath();static QMutex mutex;mutex.lock();QString text;switch(type){case QtDebugMsg:text = QString("Debug:");break;case QtWarningMsg:text = QString("Warning:");break;case QtCriticalMsg:text = QString("Critical:");break;case QtFatalMsg:text = QString("Fatal:");break;default:break;}//日志写到文件QString current_date_time = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss");QString message = QString("%1 %2%3").arg(current_date_time).arg(text).arg(msg);QFile file(LOG_FILE);file.open(QIODevice::WriteOnly | QIODevice::Append);QTextStream text_stream(&file);text_stream << message << "\r\n";file.flush();//将缓冲的数据刷新到文件file.close();mutex.unlock();
}

breviarydlg.h

#ifndef BREVIARYDLG_H
#define BREVIARYDLG_H#include <QDialog>
#include "graphicsview.h"//视口的长宽比需要与缩略图的长宽比保持一致
#define SMALL_W 400
#define SMALL_H 400//class QGraphicsScene;
class MyGraphicsScene;
class QGraphicsView;
class QGraphicsPixmapItem;class BreviaryDlg : public QDialog
{Q_OBJECT
public:BreviaryDlg(QWidget *parent = nullptr, Qt::WindowFlags f = Qt::WindowFlags());void setSize(int w,int h);void setPosSize(int x,int y,int w,int h);void setPixmap(QPixmap &pix);QSize getSize();void fitInView();void transViewPtr(GraphicsView *view);
protected:void resizeEvent(QResizeEvent *event);
//    void paintEvent(QPaintEvent *event);
public slots:void slot_setRectSize(QRect &rect);
private:QPixmap m_pixmap;
//    bool isUpdate;QRect m_rect;
//    QGraphicsScene *scene;MyGraphicsScene *scene;QGraphicsView *view;QGraphicsPixmapItem *item;GraphicsView *m_view1;
};
#endif // BREVIARYDLG_H

breviarydlg.cpp

#include "breviarydlg.h"
#include <QPalette>
#include <QPainter>
#include <QDebug>
#include <QGraphicsRectItem>
#include "MyGraphicsScene.h"
#include <QGraphicsView>BreviaryDlg::BreviaryDlg(QWidget *parent, Qt::WindowFlags f):QDialog(parent,f)/*,isUpdate(false)*/
{resize(SMALL_W,SMALL_H);setWindowFlag(Qt::FramelessWindowHint);//因为是场景所以加载背景会被场景覆盖,另外设置了无边框之后,场景也会覆盖窗口可以不用重绘窗口QPalette palette = this->palette();palette.setColor(QPalette::Background,QColor(34,34,34));setWindowOpacity(0.8);setPalette(palette);scene = new MyGraphicsScene(this);
//    scene->setBackgroundBrush(QBrush(QColor(Qt::red)));
//    scene->setForegroundBrush(QBrush(QColor(Qt::red)));
//    scene->setSceneRect(0,0,400,400);view = new QGraphicsView(scene,this);view->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);view->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);view->setGeometry(0,0,SMALL_W,SMALL_H);item = NULL;
}void BreviaryDlg::setSize(int w, int h)
{//    resize(w,h);setFixedSize(w,h);
}void BreviaryDlg::setPosSize(int x, int y, int w, int h)
{setGeometry(x,y,w,h);
}QSize BreviaryDlg::getSize()
{return QSize(SMALL_W,SMALL_H);
}void BreviaryDlg::setPixmap(QPixmap &pix)
{m_pixmap = pix;
//    isUpdate = true;qDebug()<<"setPixmap";if (item != NULL){scene->removeItem(item);delete item;}if(m_pixmap.isNull()){qDebug()<<"pixmap is null";}/*加载Pixmap图片加载不上去,画布的大小与图片的尺寸不一*/item = scene->addPixmap(m_pixmap);//QPixmap(":/new/prefix1/11.png")fitInView();
}void BreviaryDlg::fitInView()
{QRectF bounds = view->scene()->itemsBoundingRect();view->fitInView(bounds, Qt::KeepAspectRatio);
}void BreviaryDlg::transViewPtr(GraphicsView *view)
{m_view1 = new GraphicsView;m_view1 = view;connect(scene,&MyGraphicsScene::previewRectMoved,m_view1,&GraphicsView::slot_MoveView);
}void BreviaryDlg::resizeEvent(QResizeEvent *event)
{QDialog::resizeEvent(event);fitInView();
}//void BreviaryDlg::paintEvent(QPaintEvent *event)
//{//    QPainter painter(this);
//    QPen pen(QColor(34,34,34));//34,34,34
//    pen.setWidth(2);
//    pen.setStyle(Qt::SolidLine);//    painter.drawRect(0,0,SMALL_W,SMALL_H);
//}void BreviaryDlg::slot_setRectSize(QRect &rect)
{m_rect = rect;scene->onSetPreviewRect(rect);
}

config.h

#ifndef CONFIG_H
#define CONFIG_H#include <QSettings>
#include <QVariant>class Config
{public:Config(QString qstrfilename = "");virtual ~Config(void);void Set(QString,QString,QVariant);QVariant Get(QString,QString);
private:QString m_qstrFileName;QSettings *m_psetting;
};#endif // CONFIG_H

config.cpp

#include "config.h"
#include <QCoreApplication>
#include <QDebug>Config::Config(QString qstrfilename)
{if (qstrfilename.isEmpty()){m_qstrFileName = QCoreApplication::applicationDirPath() + "/Config.ini";}else{m_qstrFileName = qstrfilename;}m_psetting = new QSettings(m_qstrFileName, QSettings::IniFormat);qDebug() << m_qstrFileName;
}
Config::~Config()
{delete m_psetting;m_psetting = 0;
}
void Config::Set(QString qstrnodename,QString qstrkeyname,QVariant qvarvalue)
{m_psetting->setValue(QString("/%1/%2").arg(qstrnodename).arg(qstrkeyname), qvarvalue);
}QVariant Config::Get(QString qstrnodename,QString qstrkeyname)
{QVariant qvar = m_psetting->value(QString("/%1/%2").arg(qstrnodename).arg(qstrkeyname));return qvar;
}

dialog.h

#ifndef DIALOG_H
#define DIALOG_H#include <QDialog>
#include <QGraphicsScene>
#include "graphicsview.h"
#include "breviarydlg.h"
#include <QTimer>struct stuRatio{qreal xRatio;qreal yRatio;
};#define SMALL_W 400
#define SMALL_H 400class QVideoWidget;
class QMediaPlayer;QT_BEGIN_NAMESPACE
namespace Ui { class Dialog; }
QT_END_NAMESPACEclass Dialog : public QDialog
{Q_OBJECTpublic:Dialog(QWidget *parent = nullptr);~Dialog();//    void drawRect();stuRatio getScalingRatio();signals:void signalDrawRect(QRect &rect);void signalSetDrawRectSize();
private slots:void slot_createNaviBar(qreal scale);void slot_HvalueChanged(int value);void slot_VvalueChanged(int value);void slot_scrollValueChanged();void slot_setViewRect();void slot_timeout();
private:Ui::Dialog *ui;QGraphicsScene *scene;GraphicsView *view;QVideoWidget *video;QMediaPlayer *player;BreviaryDlg *dlg;QTimer *timer;qreal m_scale;QRect rectViewport;quint32 m_y;quint32 m_x;QSize m_viewSize;QString str;
};
#endif // DIALOG_H

dialog.cpp

#include "dialog.h"
#include "ui_dialog.h"
#include "log.hpp"
#include <QScrollBar>
#include <QSize>
#include <QGraphicsProxyWidget>
#include <QMediaPlayer>
#include <QVideoWidget>
//#include <QGraphicsRectItem>
#include <QGraphicsVideoItem>
#include <QPainter>Dialog::Dialog(QWidget *parent): QDialog(parent), ui(new Ui::Dialog),m_x(0),m_y(0),m_viewSize(100,100)
{ui->setupUi(this);resize(QSize(1200,1000));scene = new QGraphicsScene(this);view = new GraphicsView(scene,this);//设置了视图的父窗口之后就不需要调用show()
//    scene->setSceneRect(0,0,800,800);
//    view->setGeometry(0,0,800,800);
//    view->show();//场景中播放视频
//    QGraphicsRectItem *item = new QGraphicsRectItem(0,0,500,500);//item中手动嵌入的窗口的大小不会随item大小一致//    video = new QVideoWidget(this);
//    video->setWindowFlag(Qt::WindowStaysOnTopHint);
//    video->resize(500,500);
//    player = new QMediaPlayer(this);
//    player->setVideoOutput(video);
//    player->setMedia(QUrl::fromLocalFile("F:\\video\\汉化日记:第2话.mp4"));
//    player->play();//    QGraphicsProxyWidget *proxy = new QGraphicsProxyWidget(item);
//    proxy->setWidget(video);
//    scene->addItem(item);//场景中播放视频的正确打开方式QGraphicsVideoItem *item = new QGraphicsVideoItem();scene->addItem(item);item->setSize(QSizeF(800.0,800.0));player = new QMediaPlayer(this);player->setVideoOutput(item);player->setMedia(QUrl::fromLocalFile("F:\\video\\汉化日记:第2话.mp4"));player->play();connect(view,&GraphicsView::sinalCreateNavigaBar,this,&Dialog::slot_createNaviBar);dlg = NULL;str = QCoreApplication::applicationDirPath();str += "\\11.png";outPut<<"路径名:"<<str;timer = new QTimer;connect(timer,&QTimer::timeout,this,&Dialog::slot_timeout);connect(view->verticalScrollBar(),&QScrollBar::valueChanged,this,slot_VvalueChanged);connect(view->horizontalScrollBar(),&QScrollBar::valueChanged,this,slot_HvalueChanged);connect(this,&Dialog::signalSetDrawRectSize,this,&Dialog::slot_setViewRect);
}Dialog::~Dialog()
{delete ui;
}void Dialog::slot_createNaviBar(qreal scale)
{if(scale > 1){m_scale = scale;if(dlg == NULL){dlg = new BreviaryDlg(this,Qt::WindowStaysOnTopHint);//        dlg->setGeometry(100,200,400,300);//        dlg->setSize(400,300);connect(this,&Dialog::signalDrawRect,dlg,&BreviaryDlg::slot_setRectSize);//        QImage image(QSize(400,300),QImage::Format_RGB32);//        QPainter painter(&image);//        image.save("E:\\11","png");//        view->setViewport(dlg);//        dlg->setPosSize(600,500,400,300);//        QPalette palette = dlg->palette();//        palette.setColor(QPalette::Background,QColor(34,34,34));//        dlg->setWindowOpacity(0.8);//        dlg->setPalette(palette);QSize size = dlg->getSize();view->smallWinSize(size);dlg->transViewPtr(view);dlg->show();//非模态}else{dlg->show();}QPixmap pixmap(SMALL_W,SMALL_H);pixmap.fill(Qt::transparent);QPainter painter(&pixmap);painter.setRenderHint(QPainter::Antialiasing);scene->render(&painter);pixmap.save(str,"png");dlg->setPixmap(pixmap);timer->start(100);}else{if(dlg != NULL){dlg->hide();}}
}void Dialog::slot_scrollValueChanged()
{m_viewSize = view->viewportSizeHint();//获取视口大小QRect rectScene = scene->itemsBoundingRect().toRect();if (view->horizontalScrollBar()->isHidden()){rectViewport.setX(rectScene.x());rectViewport.setWidth(rectScene.width());}if(view->verticalScrollBar()->isHidden()){rectViewport.setY(0);rectViewport.setHeight(rectScene.height());}emit signalSetDrawRectSize();
}void Dialog::slot_HvalueChanged(int value)
{m_viewSize = view->viewportSizeHint();//获取视口大小outPut<<"slot_HvalueChanged"<<" "<<m_viewSize<</*" "<<rect<<" "<<*/value;if(value != 0 && dlg != NULL){if(dlg->isVisible()){m_x = value;emit signalSetDrawRectSize();}}
}void Dialog::slot_VvalueChanged(int value)
{m_viewSize = view->viewportSizeHint();//获取视口大小
//    QRect rect = view->viewPortRect();outPut<<"slot_VvalueChanged"<<" "<<m_viewSize<</*" "<<rect<<" "<<*/value;if(value != 0 && dlg != NULL){if(dlg->isVisible()){m_y = value;emit signalSetDrawRectSize();}}
}void Dialog::slot_setViewRect()
{view->viewPortSize(m_viewSize);int x = m_x / (m_viewSize.width() * m_scale)* SMALL_W;int y = m_y / (m_viewSize.height() * m_scale)* SMALL_H;int wid = SMALL_W / m_scale;int hei = SMALL_H / m_scale;outPut<<"小矩形坐标及大小:"<<"("<<m_x<<" ,"<<m_y<<" ,"<<wid<<" ,"<<hei<<")";QRect rect(x,y,wid,hei);emit signalDrawRect(rect);
}stuRatio Dialog::getScalingRatio()
{stuRatio ratio;ratio.xRatio = (qreal)SMALL_W / m_viewSize.width();ratio.yRatio = (qreal)SMALL_H / m_viewSize.height();outPut<<"横纵比:"<<ratio.xRatio<<" "<<ratio.yRatio;return ratio;
}void Dialog::slot_timeout()
{QPixmap pixmap(SMALL_W,SMALL_H);pixmap.fill(Qt::transparent);QPainter painter(&pixmap);painter.setRenderHint(QPainter::Antialiasing);scene->render(&painter);pixmap.save(str,"png");dlg->setPixmap(pixmap);
}

graphicsview.h

#ifndef GRAPHICSVIEW_H
#define GRAPHICSVIEW_H
#include <QGraphicsView>
#include <QGraphicsScene>
#include <QEvent>
#include "config.h"
//#pragma execution_characters_set("utf-8")
class GraphicsView : public QGraphicsView
{Q_OBJECT
public:GraphicsView(QWidget *parent = nullptr);GraphicsView(QGraphicsScene *scene, QWidget *parent = nullptr);
#if QT_CONFIG(wheelevent)void wheelEvent(QWheelEvent *) override;
#endifvoid setIsWheel(bool isScroll);//是否可以滚动//多边形面积qreal PolygonArea(QList<QPointF>&posList);QSize viewportSizeHint();QRect viewPortRect();void viewPortSize(QSize &size);void smallWinSize(QSize &size);
protected:bool event(QEvent *event);
//    void paintEvent(QPaintEvent *event);
signals:void signalTransScale(qreal scale);void sinalCreateNavigaBar(qreal scale);//创建缩略图
public slots:void slot_MoveView(QRect rect);
//protected:
//    void mouseMoveEvent(QMouseEvent *event);
//    void mousePressEvent(QMouseEvent *event);
//    void mouseReleaseEvent(QMouseEvent *event);
private:
//    QPointF beginPoint;bool m_isScroll;//是否可以执行滚轮放大缩小事件QPointF previous_touch_point0;QPointF previous_touch_point1;int touch_status = 0;qreal m_scale;//保存缩放比qreal firstArea;//刚接触时多边形面积Config *config;qreal upLimit;//放大的上限qreal lowLimit;//缩小的下限QSize m_viewPortWH;//视口的宽高QSize m_smallWinWH;//小窗口的宽高
};
#endif // GRAPHICSVIEW_H

graphicsview.cpp

#include "graphicsview.h"
#include "log.hpp"
#include <QWheelEvent>
#include <QScrollBar>
#include <QTouchEvent>
#include <QLineF>#if QT_CONFIG(wheelevent)
void GraphicsView::wheelEvent(QWheelEvent *e)
{if(!m_isScroll){return ;}if (e->modifiers() & Qt::ControlModifier){qreal curScale = m_scale;if (e->delta() > 0)//远离{if(curScale < upLimit){m_scale *= 1.2;emit sinalCreateNavigaBar(m_scale);scale(1.2,1.2);
//               m_scale *= 1.2;}}else{if(curScale > lowLimit){m_scale *= 0.8;emit sinalCreateNavigaBar(m_scale);scale(0.8,0.8);}}e->accept();}else{QGraphicsView::wheelEvent(e);}
//    if(m_scale > 2)
//    {emit sinalCreateNavigaBar(m_scale);
//    }
//    emit signalTransScale(1/m_scale);
//    outPut<<"视图缩放的比例:"<<1/m_scale;
}
#endifGraphicsView::GraphicsView(QWidget *parent):QGraphicsView(parent),m_isScroll(true),touch_status(0),m_scale(1),firstArea(1)
{config = new Config();upLimit = config->Get("viewScale","upScale").toFloat();lowLimit = config->Get("viewScale","lowScale").toFloat();outPut<<"upLimit:"<<upLimit<<" "<<"lowLimit:"<<lowLimit;previous_touch_point0 = QPointF(0.0,0.0);previous_touch_point1 = QPointF(0.0,0.0);setAttribute(Qt::WA_AcceptTouchEvents);//捕获touch事件
//    setRenderHint(QPainter::Antialiasing, false);setDragMode(QGraphicsView::ScrollHandDrag);setOptimizationFlags(QGraphicsView::DontSavePainterState);setViewportUpdateMode(QGraphicsView::SmartViewportUpdate);
}GraphicsView::GraphicsView(QGraphicsScene *scene, QWidget *parent):QGraphicsView(scene,parent),m_isScroll(true),touch_status(0),m_scale(1),firstArea(1)
{config = new Config();upLimit = config->Get("viewScale","upScale").toFloat();lowLimit = config->Get("viewScale","lowScale").toFloat();outPut<<"upLimit:"<<upLimit<<" "<<"lowLimit:"<<lowLimit;previous_touch_point0 = QPointF(0.0,0.0);previous_touch_point1 = QPointF(0.0,0.0);setAttribute(Qt::WA_AcceptTouchEvents);//捕获touch事件
//    setRenderHint(QPainter::Antialiasing, false);setDragMode(QGraphicsView::ScrollHandDrag);setOptimizationFlags(QGraphicsView::DontSavePainterState);setViewportUpdateMode(QGraphicsView::SmartViewportUpdate);
}void GraphicsView::setIsWheel(bool isScroll)
{m_isScroll = isScroll;
}qreal GraphicsView::PolygonArea(QList<QPointF> &posList)
{QList<QPointF> tarPos;QList<QPointF> optList = posList;int nLen = posList.size();if(nLen==3){tarPos = posList;}else if(nLen>3){for(int i=0;i<optList.size()-1;++i)//按x点进行排序{for(int j=i+1;j<optList.size();++j){if(optList[j].x()<optList[i].x()){optList.swap(i,j);}}}for(int i=0;i<3-1;++i){for(int j=i+1;j<3;++j){if(optList[j].y()<optList[i].y()){optList.swap(i,j);}}tarPos.push_back(optList[i]);}tarPos.push_back(optList[2]);for(int i=3;i<optList.size()-1;++i){for(int j=i+1;j<optList.size();++j){if(optList[j].y()>optList[i].y()){optList.swap(i,j);}}tarPos.push_back(optList[i]);}tarPos.push_back(optList[optList.size()-1]);}qreal s=1;for(int k=0;k<nLen;++k){QPointF& pos1 = tarPos[k];QPointF& pos2 = tarPos[(k+1)%nLen];s +=(pos1.x()*pos2.y()-pos2.x()*pos1.y());}s=abs(0.5*s);return s;
}QSize GraphicsView::viewportSizeHint()
{return viewport()->size();
}QRect GraphicsView::viewPortRect()
{return viewport()->rect();
}void GraphicsView::viewPortSize(QSize &size)
{m_viewPortWH = size;outPut<<"视口:"<<m_viewPortWH;
}void GraphicsView::smallWinSize(QSize &size)
{m_smallWinWH = size;outPut<<"窗口:"<<m_smallWinWH;
}bool GraphicsView::event(QEvent *event)
{switch(event->type()){case QEvent::TouchBegin:{QTouchEvent* touch = static_cast<QTouchEvent*>(event);QList<QTouchEvent::TouchPoint> touchPoints = touch->touchPoints();outPut<<"TouchBegin点的个数为:"<<touchPoints.count();return true;}case QEvent::TouchUpdate:{QTouchEvent *touchEvent = static_cast<QTouchEvent *>(event);QList<QTouchEvent::TouchPoint> touchPoints = touchEvent->touchPoints();outPut<<"TouchUpdate点的个数为:"<<touchPoints.count();if (touchPoints.count() == 2 /*&& touch_status == 1*/){if(touchEvent->touchPointStates() & Qt::TouchPointPressed){const QTouchEvent::TouchPoint &touchPoint0 = touchPoints.first();const QTouchEvent::TouchPoint &touchPoint1 = touchPoints.last();previous_touch_point0.setX(touchPoint0.pos().x());previous_touch_point0.setY(touchPoint0.pos().y());previous_touch_point1.setX(touchPoint1.pos().x());previous_touch_point1.setY(touchPoint1.pos().y());outPut<<"刚开始点:("<<previous_touch_point0.x()<<","<<previous_touch_point0.y()<<")"<<"("<<previous_touch_point1.x()<<","<<previous_touch_point1.y()<<")";touch_status=2;}if(touchEvent->touchPointStates() & Qt::TouchPointMoved){if(touch_status == 2){const QTouchEvent::TouchPoint &touchPoint0 = touchPoints.first();const QTouchEvent::TouchPoint &touchPoint1 = touchPoints.last();qreal currentScaleFactor =QLineF(touchPoint0.pos(), touchPoint1.pos()).length()/ QLineF(previous_touch_point0, previous_touch_point1).length();
//                          qreal  proper = currentScaleFactor>1?1.05:0.8;outPut<<"起点:"<<touchPoint0.pos()<<touchPoint1.pos();outPut<<"移动后:("<<previous_touch_point0.x()<<","<<previous_touch_point0.y()<<")"<<"("<<previous_touch_point1.x()<<","<<previous_touch_point1.y()<<")";outPut<<"起点线长:"<<QLineF(touchPoint0.pos(), touchPoint1.pos()).length();outPut<<"移动后线长:"<<QLineF(previous_touch_point0, previous_touch_point1).length();outPut<<"缩放参考点为:"<<currentScaleFactor;if(currentScaleFactor > 1){if(m_scale < upLimit){scale(1.2,1.2);m_scale *= 1.2;}}else{if(m_scale > lowLimit){scale(0.8,0.8);m_scale *= 0.8;}}//                          scale(proper,proper);previous_touch_point0.setX(touchPoint0.pos().x());previous_touch_point0.setY(touchPoint0.pos().y());previous_touch_point1.setX(touchPoint1.pos().x());previous_touch_point1.setY(touchPoint1.pos().y());}}}if (touchPoints.count() == 3){if(touchEvent->touchPointStates() & Qt::TouchPointPressed){QList<QPointF> pointList;QPointF siglePoint;for(int i = 0; i < touchPoints.size(); ++i){siglePoint = touchPoints[i].pos();pointList.push_back(siglePoint);}firstArea = PolygonArea(pointList);touch_status = 3;}if(touchEvent->touchPointStates() & Qt::TouchPointMoved){if(touch_status == 3){QList<QPointF> pointList;QPointF siglePoint;for(int i = 0; i < touchPoints.size(); ++i){siglePoint = touchPoints[i].pos();pointList.push_back(siglePoint);}qreal lastArea = PolygonArea(pointList);qreal currentScaleFactor = lastArea / firstArea;outPut<<"刚开始面积:"<<firstArea;outPut<<"变化后面积:"<<lastArea;outPut<<"面积比:"<<currentScaleFactor;
//                            qreal  proper = currentScaleFactor>1?1.05:0.8;
//                            scale(proper,proper);if(currentScaleFactor > 1){if(m_scale < upLimit){scale(1.2,1.2);m_scale *= 1.2;}}else{if(m_scale > lowLimit){scale(0.8,0.8);m_scale *= 0.8;}}firstArea = lastArea;}}}if (touchPoints.count() == 4){if(touchEvent->touchPointStates() & Qt::TouchPointPressed){QList<QPointF> pointList;QPointF siglePoint;for(int i = 0; i < touchPoints.size(); ++i){siglePoint = touchPoints[i].pos();pointList.push_back(siglePoint);}firstArea = PolygonArea(pointList);touch_status = 4;}if(touchEvent->touchPointStates() & Qt::TouchPointMoved){if(touch_status == 4){QList<QPointF> pointList;QPointF siglePoint;for(int i = 0; i < touchPoints.size(); ++i){siglePoint = touchPoints[i].pos();pointList.push_back(siglePoint);}qreal lastArea = PolygonArea(pointList);qreal currentScaleFactor = lastArea / firstArea;outPut<<"刚开始面积:"<<firstArea;outPut<<"变化后面积:"<<lastArea;outPut<<"面积比:"<<currentScaleFactor;
//                            qreal  proper = currentScaleFactor>1?1.05:0.8;
//                            scale(proper,proper);if(currentScaleFactor > 1){if(m_scale < upLimit){scale(1.2,1.2);m_scale *= 1.2;}}else{if(m_scale > lowLimit){scale(0.8,0.8);m_scale *= 0.8;}}firstArea = lastArea;}}}if (touchPoints.count() == 5){if(touchEvent->touchPointStates() & Qt::TouchPointPressed){QList<QPointF> pointList;QPointF siglePoint;for(int i = 0; i < touchPoints.size(); ++i){siglePoint = touchPoints[i].pos();pointList.push_back(siglePoint);}firstArea = PolygonArea(pointList);touch_status = 5;}if(touchEvent->touchPointStates() & Qt::TouchPointMoved){if(touch_status == 5){QList<QPointF> pointList;QPointF siglePoint;for(int i = 0; i < touchPoints.size(); ++i){siglePoint = touchPoints[i].pos();pointList.push_back(siglePoint);}qreal lastArea = PolygonArea(pointList);qreal currentScaleFactor = lastArea / firstArea;outPut<<"刚开始面积:"<<firstArea;outPut<<"变化后面积:"<<lastArea;outPut<<"面积比:"<<currentScaleFactor;
//                            qreal  proper = currentScaleFactor>1?1.05:0.8;
//                            scale(proper,proper);if(currentScaleFactor > 1){if(m_scale < upLimit){scale(1.2,1.2);m_scale *= 1.2;}}else{if(m_scale > lowLimit){scale(0.8,0.8);m_scale *= 0.8;}}firstArea = lastArea;}}}else if(touchEvent->touchPointStates() & Qt::TouchPointReleased){touch_status=0;}event->accept();return true;}case QEvent::TouchEnd:{event->accept();return true;}default:break;}return QGraphicsView::event(event);//QWidget::event(event);
}void GraphicsView::slot_MoveView(QRect rect)
{verticalScrollBar()->setValue(rect.y()*m_scale*m_viewPortWH.height()/m_smallWinWH.height());horizontalScrollBar()->setValue(rect.x()*m_scale*m_viewPortWH.width()/m_smallWinWH.width());
}//void GraphicsView::mouseMoveEvent(QMouseEvent *event)
//{//    if(event->buttons() & Qt::LeftButton)
//    {//        QPointF pos = event->screenPos();
//        qreal x = pos.x() - beginPoint.x();
//        qreal y = pos.y() - beginPoint.y();//        QScrollBar* verBar = verticalScrollBar();
//        int nValue = verBar->value();
//        verBar->setValue(nValue - y);//        QScrollBar* horBar = horizontalScrollBar();
//        nValue = horBar->value();
//        horBar->setValue(nValue - x);
//    }
//    QGraphicsView::mouseMoveEvent(event);
//}//void GraphicsView::mousePressEvent(QMouseEvent *event)
//{//    if(event->button() == Qt::LeftButton)
//    {//        beginPoint = event->screenPos();
//    }
//    QGraphicsView::mousePressEvent(event);
//}//void GraphicsView::mouseReleaseEvent(QMouseEvent *event)
//{//    QGraphicsView::mouseReleaseEvent(event);
//}

MyGraphicsScene.h

#pragma once//#include <vld.h>
#include <QGraphicsScene>class MyGraphicsScene : public QGraphicsScene
{Q_OBJECTpublic:MyGraphicsScene(QObject *parent = nullptr);virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *mouseEvent);virtual void mousePressEvent(QGraphicsSceneMouseEvent *mouseEvent);virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *mouseEvent);Q_SIGNALS:void previewRectMoved(QRect rect);public Q_SLOTS:void onSetPreviewRect(QRect rect);private:QGraphicsRectItem* m_pRectItem;QRect m_rectSaved;bool m_bRectClicked;QPoint m_ptRectRelated;     // 鼠标点击时,相对于红色矩形框的位置
};

MyGraphicsScene.cpp

#include "MyGraphicsScene.h"
#include <QGraphicsSceneMouseEvent>
#include <QGraphicsRectItem>
#include <QDebug>MyGraphicsScene::MyGraphicsScene(QObject *parent): QGraphicsScene(parent), m_bRectClicked(false)
{m_pRectItem = new QGraphicsRectItem(0, 0, 0, 0);QPen penRectItem = QPen(QColor(255, 0, 0));penRectItem.setWidth(2);m_pRectItem->setPen(penRectItem);m_pRectItem->setZValue(1);addItem(m_pRectItem);
}void MyGraphicsScene::onSetPreviewRect(QRect rect)
{m_rectSaved = rect;// 内缩几个像素,用矩形外边框来标示viewport显示区域m_pRectItem->setRect(rect.x() -2/*+ 5*/, rect.y() - 2/*+ 5*/, rect.width() - 4, rect.height() - 4);
}void MyGraphicsScene::mouseMoveEvent(QGraphicsSceneMouseEvent *mouseEvent)
{QGraphicsScene::mouseMoveEvent(mouseEvent);if (m_bRectClicked) {QPoint ptTopLeft = mouseEvent->scenePos().toPoint() - m_ptRectRelated;m_rectSaved.setTopLeft(ptTopLeft);emit previewRectMoved(m_rectSaved);}
}void MyGraphicsScene::mousePressEvent(QGraphicsSceneMouseEvent *mouseEvent)
{QGraphicsScene::mousePressEvent(mouseEvent);if (m_rectSaved.contains(mouseEvent->scenePos().x(), mouseEvent->scenePos().y())) {m_bRectClicked = true;m_ptRectRelated = mouseEvent->scenePos().toPoint() - m_rectSaved.topLeft();}
}void MyGraphicsScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *mouseEvent)
{QGraphicsScene::mouseReleaseEvent(mouseEvent);m_bRectClicked = false;
}

所有程序的代码上面已经全部贴出,由于还涉及到ui文件,所以要看运行效果,需先创建基于对话框QDialog的程序,在此基础上修改添加创建对应的文件,另外还需注意,修改你本地的视频所在路径,并将配置文件拷贝到可执行目录下,qt可能还不能直接运行,因为缺少解码器,这时根据提示下载安装解码器,解决掉“那个”问题之后便可以运行,查看相应的效果。
注意:

  1. 修改需要你需要播放的视频的路径,重新指定需要播放的视频;
  2. 将下面的配置文件拷贝到可执行目录下。
    Config.ini

[viewScale]
upScale = 3
lowScale = 0.3

移动场景在其缩略图中显示场景中所显示的区域相关推荐

  1. 所有库在门不显示封装_COB全天候通透屏,在商业显示中的场景应用

            一.COB集成封装LED显示产品已成为行业发展大势 从2015年开始行业就已经预测到COB集成封装就是未来LED显示领域户内外小间距的发展方向,在不同的文章上也可以看到这样的推论:&q ...

  2. 在SAP PI中建立场景

    在SAP PI中建立场景 如果需要在PI中建立场景(scenario),要从主页开始. 主页界面如下: 主页有以下四个工作区的超链接: 企业服务库(ESR) 集成目录(ID) 系统规划(SL) 配置和 ...

  3. Unity制作游戏中的场景

    Unity制作游戏中的场景 1.2.3  场景 在Unity中,场景(Scene)就是游戏开发者制作游戏时,所使用的游戏场景.它是一个三维空间,对应的三维坐标轴分别是X轴.Y轴和Z轴本文选自Unity ...

  4. HTML5游戏开发(四):飞机大战之显示场景和元素

    <HTML5游戏开发>系列文章的目的有:一.以最小的成本去入门egret小项目开发,官方的教程一直都是面向中重型:二.egret可以非常轻量:三.egret相比PIXI.js和sprite ...

  5. 3D场景中选取场景中的物体。

    杨航最近在学Unity3D 在一些经典的游戏中,需要玩家在一个3D场景中选取场景中的物体.例如<仙剑奇侠传>,选择要攻击的敌人时.为我方角色增加血量.为我方角色添加状态,通常我们使 ...

  6. 面试官系统精讲Java源码及大厂真题 - 35 经验总结:各种锁在工作中使用场景和细节

    35 经验总结:各种锁在工作中使用场景和细节 富贵必从勤苦得. 引导语 本章主要说一说锁在工作中的使用场景,主要以 synchronized 和 CountDownLatch 为例,会分别描述一下这两 ...

  7. 面试官系统精讲Java源码及大厂真题 - 25 整体设计:队列设计思想、工作中使用场景

    25 整体设计:队列设计思想.工作中使用场景 人生太短,要干的事太多,我要争分夺秒. --爱迪生 引导语 本章我们学习了 LinkedBlockingQueue.ArrayBlockingQueue. ...

  8. Unity3D中关于场景销毁时事件调用顺序的一点记录

    先说一下我遇到的问题,我弄了一个对象池管理多个对象,对象池绑定在一个GameObject上,每个对象在OnBecameInvisible时会进行回收(即移出屏幕就回收),但是当场景切换或停止运行程序时 ...

  9. Redis学习(一)—生活中实用场景帮助理解redis的五种基本数据类型

    Redis实例目录 (一)String (1)业务场景1--分库分表后获取唯一id (2)业务场景2--数据时效性设置 (3)业务场景3--高频数据访问显示 实现方式一 实现方式二 (二)Hash ( ...

  10. FLASH 中的场景,图层以及层的理解

    1对初学者来说,FLASH(这里一FLASH8为例)的场景.图层(lawyer)和层(level)很容易引起困惑的3个概念,FLASH动画的各个对象的位置关系是按照一定的层状结构来呈现的.他的根是场景 ...

最新文章

  1. Linux 学习手记(1):命令行BASH的基本操作
  2. 设计模式之观察者模式学习笔记
  3. 华润网络签约神策数据 数据赋能打造跨行业综合移动服务生态圈
  4. MySql根据经纬度查询任意距离范围内数据
  5. MFC中滑动条的使用
  6. 【题解】lugu P4095 Eden的新背包问题
  7. 动态规划算法入门---java版
  8. Jquery 寻找父、子、兄弟节点
  9. php实现无限级树型菜单(函数递归算法)
  10. Arrays工具、二维数组以及LeetCode练习题
  11. mysql索引选择_MySQL 索引选择原则
  12. python3.7.2安装步骤-python安装升级详细步骤 Python2 升级 Python3
  13. CentOS7搭建FTP文件服务器
  14. MogDB官网正式亮相!单机256万tpmC再创佳绩
  15. 计算机分磁盘,磁盘分区怎么分
  16. 从零开始设计RISC-V处理器——指令系统
  17. Windows下的Rsync(cwRsync)
  18. 高中信息技术简答题汇总
  19. Hadoop培训视频教程
  20. java.io.IOException: Cleartext HTTP traffic to xxx.xxx.xxx.xxx not permitted

热门文章

  1. 如何在golang代码里面解析容器镜像
  2. 2021云栖大会开源引力峰会发布的战略合作,Grafana服务到底是什么?
  3. OceanBase再破纪录!核心成员陈萌萌:坚持HTAP就是坚持我们做数据库的初心
  4. 战“疫”期,阿里云云效团队在家高效开发实录
  5. 透过 In-memory Channel 看 Knative Eventing 中 Broker/Trigger 工作机制
  6. 开源Elasticsearch云托管服务,专享企业级服务
  7. 英雄帖!移动云首批最有价值专家(MVP)招募开始了!
  8. 建设数据中台之前,建议先看这份企业数据能力测评 | 大咖说中台
  9. 44年前的今天,改变世界的TA诞生了! | 极客头条
  10. 有问有答 | 你真的理解微服务架构吗?