QT笔记(5)——Qt图形视图框架实例
来源:互联网 发布:黑产数据交易平台 编辑:程序博客网 时间:2024/06/04 19:43
Qt的图形视图框架很强大,同时也很复杂,这里做了一个简单的练习,对图片加载,并移动放缩,的一个图片查看器;需要继承图元类;
下面直接贴源码了:
新建一个widget应用,然后添加如下:
pixitem.h:
#ifndef PIXITEM_H#define PIXITEM_H#include <QGraphicsItem>#include <QPixmap>#include <QPainter>#include <QRectF>#include <QMouseEvent>#include <QPointF>#include <QDragEnterEvent>#include <QGraphicsSceneWheelEvent>#include <QGraphicsObject>//枚举方便传递enum Enum_ZoomState{ NO_STATE, RESET, ZOOM_IN, ZOOM_OUT};//放大缩小值范围enum Enum_ZoomTimes{ ZOOM_IN_TIMES = 50, ZOOM_OUT_TIMES = -50,};//直接继承QGraphicsObject,这样有信号和槽QGraphicsItem没有信号和槽功能class PixItem :public QGraphicsObject//public QGraphicsItem//继承自图元类,实现自定义的图元,qt预置的有直线,椭圆,文本图元,矩形图元等{public: PixItem(QPixmap *pixmap); //构造函数初始化了变量pix QRectF boundingRect() const; //实现自己的boundingRect 图元边界方法,继承QGraphicsItem必须要初始化话的虚函数 //完成以图元坐标系为基础增加两个像素点的冗余的工作 void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); //重画图形函数 void wheelEvent(QGraphicsSceneWheelEvent *event);//滚轮放大缩小 void setZoomState(const int &zoomState);//设置图像恢复原始 void mousePressEvent(QGraphicsSceneMouseEvent *event);//用于移动图像 void mouseMoveEvent(QGraphicsSceneMouseEvent *event);//用于移动图像 void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);//用于移动图像 void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event);//双击恢复图像 int getScaleValue() const;//获取当前图元放缩值 void setScaleValue(const int &);//返回放放缩值 void setValue(const QPointF &);//返回窗口大小值 int widx; int widy;signals:private: qreal m_scaleValue; //缩放值 QPixmap pix; //作为图元显示的图片 int m_zoomState; bool m_isMove; QPointF m_startPos;};#endif // PIXITEM_H
pixitem.cpp:
#include "pixitem.h"#include <QDebug>#include <QGraphicsSceneMouseEvent>#include <QPointF>#include <QGraphicsSceneDragDropEvent>#include <QDrag>#include <math.h>#include <QMessageBox>#include <QGraphicsObject>#include "widget.h"//构造函数初始化了变量pixPixItem::PixItem(QPixmap *pixmap){ pix = *pixmap; setAcceptDrops(true); //设置可拖拽 m_scaleValue = 0;//放缩值初始化 m_isMove = false;//不可移动 widx=0; widy=0;}//实现自己的图元边界函数QRectF PixItem::boundingRect() const{ return QRectF(-pix.width()/2, -pix.height()/2, pix.width(), pix.height());//需要对应图元,不然出现残影}//只需QPainter的drawPixmap()函数将图元图片绘出即可void PixItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *){ painter->drawPixmap(-pix.width()/2, -pix.height()/2, pix);//需要对应边界函数}//鼠标点击事件void PixItem::mousePressEvent(QGraphicsSceneMouseEvent *event){ m_startPos = event->pos(); m_isMove = true;//图元是否可以移动//////下面测试代码// QPointF m_center;// m_center=mapToScene(0,0);//坐标映射,图元坐标映射到窗口// double a =m_center.x();// QString str=QString::number(a,10,0); // 这是你的变量// QMessageBox mesg;// mesg.about(NULL,QString::fromLocal8Bit("图片大小") , str);}void PixItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event){// if(sceneBoundingRect().width()<widx&&sceneBoundingRect().height()<widy)// {// m_isMove = false;//小于窗口时候不可以移动// }// if(sceneBoundingRect().width()>widx-20||sceneBoundingRect().height()>widy-20)// {// QPointF m_center;// m_center=mapToScene(0,0);//图元中心坐标// QPointF points = event->pos()- m_startPos;// int wx,wy;// wx=sceneBoundingRect().width()-widx;// wy=sceneBoundingRect().height()-widy;// if(pow(1.1,wx/2)>pow(1.1,m_center.x())||pow(1.1,wy/2)>pow(1.1,m_center.y()))// {// moveBy(points.x(),points.y());// }// m_isMove = false;// } if(m_isMove) { QPointF point =mapToScene(event->pos())-mapToScene(m_startPos); moveBy(point.x(),point.y()); // 鼠标点击后并移动则图元相应移动,进行了图元坐标映射,映射到窗口中 } }void PixItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *){ m_isMove = false;}//双击复位void PixItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event){ // int ag=sceneBoundingRect().width(); // int bg=sceneBoundingRect().height(); // QString strag=QString::number(ag,10,0); // 这是你的变量 // QString strbg=QString::number(bg,10,0); // 这是你的变量 // QString strg = QString::fromLocal8Bit("图片宽度:%1,图片高度:%2").arg(strag).arg(strbg); // QMessageBox mesgg; // mesgg.about(NULL,QString::fromLocal8Bit("图片信息") ,strg); setPos(0,0); m_scaleValue = 0; setScale(1); setTransformOriginPoint(0, 0); //做了坐标映射,将图片回复到窗口中心 QPointF m_center; m_center=mapToScene(0,0); if(m_center.x()!=0||m_center.y()!=0) { if(m_center.x()>0&&m_center.y()>0) moveBy(-m_center.x(), -m_center.y()); if(m_center.x()<0&&m_center.y()<0) moveBy(m_center.x(), m_center.y()); if(m_center.x()>0&&m_center.y()<0) moveBy(-m_center.x(), m_center.y()); if(m_center.x()<0&&m_center.y()>0) moveBy(m_center.x(), -m_center.y()); }}//使用滚轮整体缩放void PixItem::wheelEvent(QGraphicsSceneWheelEvent *event){ setZoomState(NO_STATE); int scaleValue = m_scaleValue; if(event->delta() > 0) //delta()为正,滚轮向上滚 { scaleValue++; } else { scaleValue--; } /////测试代码以下 // if(scaleValue<=0)//小于窗口时候自动回中央 // { // setPos(0,0); // QPointF m_center; // m_center=mapToScene(0,0); // if(m_center.x()!=0||m_center.y()!=0) // { // if(m_center.x()>0&&m_center.y()>0) moveBy(-m_center.x(), -m_center.y()); // if(m_center.x()<0&&m_center.y()<0) moveBy(m_center.x(), m_center.y()); // if(m_center.x()>0&&m_center.y()<0) moveBy(-m_center.x(), m_center.y()); // if(m_center.x()<0&&m_center.y()>0) moveBy(m_center.x(), -m_center.y()); // } // } //////////////*************以上 if (scaleValue > ZOOM_IN_TIMES || scaleValue < ZOOM_OUT_TIMES) return; m_scaleValue = scaleValue; qreal s; if(m_scaleValue > 0) { s = pow(1.1, m_scaleValue); //放大 计算x的y方次 参数都是double类型 } else { s = pow(1 / 1.1, -m_scaleValue); //缩小 } setScale(s);//setScale设置比例放缩,内置的处理图像放缩的方法 if(sceneBoundingRect().width()>=widx||sceneBoundingRect().height()>=widy) { // m_isMove = false; setTransformOriginPoint(event->pos());//基于图元坐标内鼠标指针变换中心 } // QPointF m_center; // m_center=mapToScene(event->pos().x(),event->pos().y());//转换至窗口后指针变换中心 // setTransformOriginPoint(m_center); }//从widget获取的缩放值,用于同步滚轮和按键void PixItem::setScaleValue(const int &scaleValue){ if (scaleValue > ZOOM_IN_TIMES || scaleValue < ZOOM_OUT_TIMES) return; m_scaleValue = scaleValue;////////*******测试代码以下// if(scaleValue<=0)//小于窗口时候自动回中央// {// setPos(0,0);// QPointF m_center;// m_center=mapToScene(0,0);// if(m_center.x()!=0||m_center.y()!=0)// {// if(m_center.x()>0&&m_center.y()>0) moveBy(-m_center.x(), -m_center.y());// if(m_center.x()<0&&m_center.y()<0) moveBy(m_center.x(), m_center.y());// if(m_center.x()>0&&m_center.y()<0) moveBy(-m_center.x(), m_center.y());// if(m_center.x()<0&&m_center.y()>0) moveBy(m_center.x(), -m_center.y());// }// } qreal s; if(m_scaleValue > 0) { s = pow(1.1, m_scaleValue); //放大 计算x的y方次 参数都是double类型,去除正负数 } else { s = pow(1 / 1.1, -m_scaleValue); //缩小 } setScale(s);}//复原图像void PixItem::setZoomState(const int &zoomState){ m_zoomState = zoomState; if (m_zoomState == RESET) { m_scaleValue = 0; setScale(1); setTransformOriginPoint(0, 0); }}//获取放缩值int PixItem::getScaleValue() const{ return m_scaleValue;}//返回窗口值void PixItem::setValue(const QPointF &pointxy){ QPointF p; p=pointxy; widx=p.x(); widy=p.y();}
在widget.h:
#ifndef WIDGET_H#define WIDGET_H#include <QWidget>#include"pixitem.h"#include <QGraphicsView> //视图类#include <QGraphicsScene> //场景类#include <QGraphicsItem> //图元类#include <math.h>#include <QWheelEvent>namespace Ui {class Widget;}class Widget : public QWidget{ Q_OBJECTpublic: explicit Widget(QWidget *parent = 0); ~Widget();protected: void mousePressEvent(QMouseEvent *e); void mouseMoveEvent(QMouseEvent *e); void mouseReleaseEvent(QMouseEvent *e); void mouseDoubleClickEvent(QMouseEvent *e); void wheelEvent(QWheelEvent *event);private slots: void my_change();//用于接收放缩值变化 void on_spinBox_valueChanged(int arg1);//系统自动生成槽函数,检测对应控件值 void resetzoom();//恢复图像 void on_B_OpenFile_clicked();//打开文件按钮 void on_B_Boost_clicked();//放大按钮 void on_B_Reduce_clicked();//缩小按钮private: Ui::Widget *ui; QPoint last; //点 PixItem *pixItem; //自定义的图元类 QGraphicsScene *m_graphicsScene; //场景 QGraphicsView *m_graphicsView; int wt; int ht;};#endif // WIDGET_H
在widget.cpp:
#include "widget.h"#include "ui_widget.h"#include <QDebug>#include <QFileDialog>#include <QPolygon>#include <QMouseEvent>#include <QMessageBox>#include <QGraphicsObject>#include "pixitem.h"Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget){ ui->setupUi(this); // this->setWindowFlags(Qt::FramelessWindowHint | // Qt::WindowSystemMenuHint | // Qt::WindowMinimizeButtonHint);//隐藏窗口标题栏和外框 //this->setAttribute(Qt::WA_TranslucentBackground);//设置背景透明 pixItem = new PixItem(new QPixmap("D:/1.jpg")); //将该图元对象添加到场景中,并设置此图元在场景中的位置为中心(0,0) m_graphicsScene = new QGraphicsScene; //new 一个新的场景对象 ui->graphicsView->setSceneRect(-10/2,-10/2,10,10); //设置开启滚动条范围,不然即使隐藏了滚动条后还是有滚动效果 ui->graphicsView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);//隐藏横向滚动条 ui->graphicsView->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);//隐藏纵向滚动条 ui->graphicsView->setScene(m_graphicsScene);//添加场景 m_graphicsScene->addItem(pixItem);//将图元添加到场景中 pixItem->setPos(0,0);//中心位置 QObject::connect(pixItem,SIGNAL(scaleChanged()), this,SLOT(my_change()));//自定义信号和槽获取scale值反馈出来 QObject::connect(ui->spinBox,SIGNAL(valueChanged(int)), ui->horizontalSlider,SLOT(setValue(int)));//spinBox值与滑条对应 QObject::connect(ui->horizontalSlider,SIGNAL(valueChanged(int)), ui->spinBox,SLOT(setValue(int)));//滑条与spinBox值对应 ui->horizontalSlider->setValue(0);//滑条初始值,范围值在窗口设计器里设置了 QObject::connect(ui->B_ReZoom,SIGNAL(clicked(bool)), this,SLOT(resetzoom()));//复位按钮}Widget::~Widget(){ delete ui;}//下面代码可以不添加//////////////////******接下*******/////////////void Widget::mousePressEvent(QMouseEvent *e){ last = e->globalPos(); //鼠标点击点位 wt=width();//获取窗口大小 ht=height();//同上 //下面注释的代码为了检测值用 // int a=wt; // int b=ht; // QString stra=QString::number(a,10,0); // 这是你的变量 // QString strb=QString::number(b,10,0); // 这是你的变量 // QString str = QString::fromLocal8Bit("窗口宽度:%1,窗口高度:%2").arg(stra).arg(strb); // QMessageBox mesg; // mesg.about(NULL,QString::fromLocal8Bit("窗口信息") ,str); QPointF p(wt,ht);//定义为点 pixItem->setValue(p);//传到pixitem类}void Widget::mouseMoveEvent(QMouseEvent *e){ //下面代码是移动窗口用,在无标题和窗口外框情况下用 int dx = e->globalX() - last.x(); int dy = e->globalY() - last.y(); last = e->globalPos(); move(x()+dx, y()+dy);}void Widget::mouseReleaseEvent(QMouseEvent *e){ //下面代码是移动窗口用,在无标题和窗口外框情况下用 int dx = e->globalX() - last.x(); int dy = e->globalY() - last.y(); move(x()+dx, y()+dy);}///////////*********接上*************/////////双击恢复图像void Widget::mouseDoubleClickEvent(QMouseEvent *e){ ////////***********图片复原代码**************///// pixItem->setPos(0,0); pixItem->setScaleValue(1); pixItem->setZoomState(NO_STATE); ui->horizontalSlider->setValue(0); //////////////**********下面注释为测试用***********//////////// // int ag=pixItem->sceneBoundingRect().width();//图元边缘 // int bg=pixItem->sceneBoundingRect().height(); // QString strag=QString::number(ag,10,0); // 这是你的变量 // QString strbg=QString::number(bg,10,0); // 这是你的变量 // QString strg = QString::fromLocal8Bit("图片宽度:%1,图片高度:%2").arg(strag).arg(strbg); // QMessageBox mesgg; // mesgg.about(NULL,QString::fromLocal8Bit("图片信息") ,strg); // int ap=pixItem->boundingRect().width();//图片边缘 // int bp=pixItem->boundingRect().height(); // QString strap=QString::number(ap,10,0); // 这是你的变量 // QString strbp=QString::number(bp,10,0); // 这是你的变量 // QString strp = QString::fromLocal8Bit("图片宽度:%1,图片高度:%2").arg(strap).arg(strbp); // QMessageBox mesgp; // mesgp.about(NULL,QString::fromLocal8Bit("图片信息") ,strp); // wt=width();//窗口大小 // ht=height(); // int a=wt; // int b=ht; // QString stra=QString::number(a,10,0); // 这是你的变量 // QString strb=QString::number(b,10,0); // 这是你的变量 // QString str = QString::fromLocal8Bit("窗口宽度:%1,窗口高度:%2").arg(stra).arg(strb); // QMessageBox mesg; // mesg.about(NULL,QString::fromLocal8Bit("窗口信息") ,str);}//滚轮滚动图片缩小放大void Widget::wheelEvent(QWheelEvent *event){ pixItem->setZoomState(NO_STATE);//枚举,对应pixitem类中 int scaleValue=pixItem->getScaleValue();//获取ScaleValue值(放大缩小值) if(event->delta() > 0) //delta()为正,滚轮向上滚 { scaleValue++; ui->horizontalSlider->setValue(scaleValue);//同步滑条 } else { scaleValue--; ui->horizontalSlider->setValue(scaleValue);//同步滑条 } pixItem->setScaleValue(scaleValue);//重新设置ScaleValue值(放大缩小值)}//自定义槽函数接受pixitem类放大缩小值void Widget::my_change(){ ui->horizontalSlider->setValue(pixItem->getScaleValue());//获取图元的放大缩小值}//系统内置spinBox槽函数,在设计窗口选中控件,右键添加valueChanged,当值改变时候自动启动void Widget::on_spinBox_valueChanged(int arg1){ pixItem->setZoomState(NO_STATE);//对应图元类中放大缩小原始枚举项 pixItem->setScaleValue(arg1); //获取控件改变的值 wt=width(); ht=height(); QPointF p(wt,ht); pixItem->setValue(p);//将窗口值传给pixitem类 //////测试代码//// // int a=wt; // int b=ht; // QString stra=QString::number(a,10,0); // 这是你的变量 // QString strb=QString::number(b,10,0); // 这是你的变量 // QString str = QString::fromLocal8Bit("窗口宽度:%1,窗口高度:%2").arg(stra).arg(strb); // QMessageBox mesg; // mesg.about(NULL,QString::fromLocal8Bit("窗口信息") ,str);}//复原函数void Widget::resetzoom(){ pixItem->setPos(0,0);//复原位置 pixItem->setScaleValue(0);//复原比例 pixItem->setZoomState(NO_STATE); ui->horizontalSlider->setValue(0);//滑条值}//打开文件按钮void Widget::on_B_OpenFile_clicked(){ QString fileName = QFileDialog::getOpenFileName( this, tr("open image file"), "./", tr("Image files(*.bmp *.jpg *.pbm *.pgm *.png *.ppm *.xbm *.xpm);;All files (*.*)")); if(fileName.isEmpty()) { // QMessageBox::warning(this, tr("警告"), tr("打开图片失败,请重新选择图片!"),NULL, QMessageBox::Yes); return; } m_graphicsScene->removeItem(pixItem); //将上一个图元从场景中移除,重新添加新的图元 pixItem = new PixItem(new QPixmap(fileName)); ui->graphicsView->setScene(m_graphicsScene);//添加到场景中 m_graphicsScene->addItem(pixItem); pixItem->setPos(0,0); QObject::connect(pixItem,SIGNAL(scaleChanged()),this,SLOT(my_change()));//刷新一下链接}//放大按钮void Widget::on_B_Boost_clicked(){ int a=ui->spinBox->value()+1; ui->horizontalSlider->setValue(a);}//缩小按钮void Widget::on_B_Reduce_clicked(){ int a=ui->spinBox->value()-1; ui->horizontalSlider->setValue(a);}运行效果如下:
阅读全文
0 0
- QT笔记(5)——Qt图形视图框架实例
- QT图形视图框架
- QT图形视图框架
- Qt图形视图框架
- QT 图形视图框架
- QT图形视图框架
- (转)Qt图形视图框架(一)
- QT图形视图框架(待完成)
- Qt图形视图框架(一)
- Qt图形视图框架(一)
- Qt图形视图框架(一)
- qt之图形视图框架(上)
- qt之图形视图框架(下)
- Qt图形视图框架(五) 变换
- Qt之图形视图框架
- Qt之图形视图框架
- Qt之图形视图框架
- Qt之图形视图框架
- 实现简易的AOP框架(一)
- C和C++中*与&的用法
- Android单位转换 (px、dp、sp之间的转换工具类)
- java多线程系列 join java多线程:
- script.sh脚本实现功能
- QT笔记(5)——Qt图形视图框架实例
- 接口测试工具postman安装及简单使用
- linux dup dup2刍议
- XUtils框架详解+使用
- jsp+js+socket实现javaweb网页聊天室
- C语言基础之指针
- Hadoop入门案例(六)之二次排序,全排序基础下的二次排序
- Linux16.04安装Matlab2016b详细教程
- ZOJ--1091:Knight Moves(dfs)