qt QGraphicsView绘图进阶重写QGraphicsPolygonItem或者QGraphicsPathItem类实现多线段功能,并能够显示、修改多线段节点 您所在的位置:网站首页 cad指定坐标点画直线不显示输入框 qt QGraphicsView绘图进阶重写QGraphicsPolygonItem或者QGraphicsPathItem类实现多线段功能,并能够显示、修改多线段节点

qt QGraphicsView绘图进阶重写QGraphicsPolygonItem或者QGraphicsPathItem类实现多线段功能,并能够显示、修改多线段节点

2024-07-18 04:56| 来源: 网络整理| 查看: 265

目录 一、具体功能描述二、具体代码实现01 重写QGraphicsRectItem类生成多线段节点SizeHandleRect类02 重写QGraphicsPolygonItem类或者QGraphicsPathItem类生成多线段Polylines类03 重写QGraphicsScene类修改事件执行04 重写QGraphicsView类A. QGraphicsView实现指定位置放大缩小B.QGraphicsView 上下左右方向键移动窗体内容显示C.QGraphicsView 以及自适应显示QGraphicsScene内容D. 带入重写的QGraphicsView事件中,实现功能

一、具体功能描述

重写QGraphicsPolygonItem/类或者QGraphicsPathItem类实现绘制多线段功能,并能够对节点进行移动,删除,同时重写 QGraphicsScene与QGraphicsView已实现对场景的指定位置缩放大小,上下左右键移动显示内容等; 搭配风速的自记纸实例,能完整的描绘出迹线轨迹,同时移动轨迹节点。 完整项目代码文件请查看下载资源,具体操作示例如下图示: 在这里插入图片描述

二、具体代码实现 01 重写QGraphicsRectItem类生成多线段节点SizeHandleRect类

多线段的节点,有画线的节点和外接矩形的节点,在添加节点是根据不同类型生成不同的节点,同时声明各种枚举作为矩形常量与状态,由于需要移动节点类型需要对QGraphicsRectItem类的按住移动事件进行重写; 同时作为多线段的子节点,需要添加一个显示状态和唯一uuid标识方便进行节点的删除与移动;

enum { SELECTION_HANDLE_SIZE = 6, SELECTION_MARGIN = 10 };//节点宽度大小 enum SelectionHandleState { SelectionHandleOff, SelectionHandleInactive, SelectionHandleActive };//显示状态 enum { Handle_None = 0 , LeftTop , Top, RightTop, Right, RightBottom, Bottom, LeftBottom, Left };//边框节点所在位置 class SizeHandleRect :public QGraphicsRectItem { public: enum { Type = UserType + 2 }; //设置类型,用于匹配到的内容判断类型 int type() const override { return Type; } SizeHandleRect(QGraphicsItem* parent , QString d , bool control = false ); SizeHandleRect(QGraphicsItem* parent ,QPointF QPo, QString d , bool control = false ); QString dir() const { return m_dir; } void setState(SelectionHandleState st);//设置当前状态 void move(qreal x, qreal y ); SelectionHandleState m_state;//显示状态 QColor borderColor;//绘色 QPointF QPoLocats; protected: void mousePressEvent(QGraphicsSceneMouseEvent *event) override; void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override; void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override; void hoverEnterEvent(QGraphicsSceneHoverEvent *e ) override;//获取鼠标 void hoverLeaveEvent(QGraphicsSceneHoverEvent *e ) override;//鼠标移开 void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); private: const QString m_dir;//唯一标识 bool m_controlPoint;//是否是矩形框的节点还是多线段的节点 QPoint C_down;//按下坐标 };

节点相关功能具体实现: 1.实例化内容时,隐藏并添加相关信息

SizeHandleRect::SizeHandleRect(QGraphicsItem* parent ,QPointF QPo , QString d, bool control) :QGraphicsRectItem(-SELECTION_HANDLE_SIZE/2, -SELECTION_HANDLE_SIZE/2, SELECTION_HANDLE_SIZE, SELECTION_HANDLE_SIZE,parent) ,m_dir(d) ,m_controlPoint(control) ,m_state(SelectionHandleOff) ,borderColor("black") ,QPoLocats(QPo) { this->setAcceptHoverEvents(true); setFlag(QGraphicsItem::ItemIgnoresTransformations,true); setFlag(QGraphicsItem::ItemIsMovable, true); setFlag(QGraphicsItem::ItemIsSelectable, true); setFlag(QGraphicsItem::ItemSendsGeometryChanges, true); hide(); }

2.重绘SizeHandleRect类型内容显示,设置当前节点状态

//print void SizeHandleRect::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { painter->save(); painter->setPen(Qt::SolidLine); painter->setBrush(QBrush(borderColor)); painter->setRenderHint(QPainter::Antialiasing,false); if ( m_controlPoint ) { painter->setPen(QPen(Qt::red,Qt::SolidLine)); painter->setBrush(Qt::green); painter->drawEllipse(rect().center(),3,3); }else painter->drawRect(rect()); painter->restore(); } //设置节点内容 void SizeHandleRect::setState(SelectionHandleState st) { if (st == m_state) return; switch (st) { case SelectionHandleOff: hide(); break; case SelectionHandleInactive: case SelectionHandleActive: show(); break; } borderColor = Qt::white; m_state = st; }

3.节点移动以及获取焦点事件 在重写事件时,为了不移除继承的类型的事件方法,可以通过 QGraphicsRectItem::mousePressEvent(event); 这种方式继续执行继承的类型事件方法;

void SizeHandleRect::mousePressEvent(QGraphicsSceneMouseEvent *event) { setCursor(Qt::ClosedHandCursor); QGraphicsRectItem::mousePressEvent(event); } void SizeHandleRect::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { QGraphicsRectItem::mouseMoveEvent(event); //移动时修改节点所在位置 if( parentItem()->type() == Polylines::Type) { Polylines * line=qgraphicsitem_cast(parentItem()); line->UpdatePoint(dir(),QPointF(this->pos().x(),this->pos().y())); QPoLocats=QPointF(this->pos().x(),this->pos().y()); } } void SizeHandleRect::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { setCursor(Qt::OpenHandCursor); QGraphicsRectItem::mouseReleaseEvent(event); } void SizeHandleRect::hoverEnterEvent(QGraphicsSceneHoverEvent *e) { borderColor = Qt::blue; update(); QGraphicsRectItem::hoverEnterEvent(e); } void SizeHandleRect::hoverLeaveEvent(QGraphicsSceneHoverEvent *e) { borderColor = Qt::white; setCursor(Qt::ArrowCursor); update(); QGraphicsRectItem::hoverLeaveEvent(e); } 02 重写QGraphicsPolygonItem类或者QGraphicsPathItem类生成多线段Polylines类

生成的Polylines类需要保存子节点SizeHandleRect的集合以及坐标点与唯一标识的内容,

public: enum { Type = UserType + 1 }; int type() const override { return Type; } public: typedef QList Handles; Handles m_handles; // QMap 插入后再遍历是按照key的顺序来排序的(汉字除外,汉字的排序顺序很奇怪,不是正常的字母顺序); // QHash插入后再遍历是没有顺序的; // QMap MapList; // QHash MapList; QList pairs; QBrush m_brush;

也需要对节点的新增,删除,修改,刷新方法

//添加节点 void Polylines::AddPointNotSort(QPointF Po) { QUuid id = QUuid::createUuid(); QString strId = id.toString(); SizeHandleRect *shr = new SizeHandleRect(this, Po,strId, true); shr->setState(SelectionHandleActive); QPair pairone(strId,Po); pairs.append(pairone); m_handles.append(shr); update(); } //坐标点批量添加 void Polylines::AddPoint(QList Polist) { int count=0; foreach(QPoint it ,Polist) { count++; // QString str = QString("%1").arg(count,10,10,QLatin1Char('0')); QUuid id = QUuid::createUuid(); QString strId = id.toString(); /* QDateTime local(QDateTime::currentDateTime()); QString localTime = local.toString("yyyy-MM-dd:hh:mm:ss.zzz");*/ //QMap按照key自动排序输出 SizeHandleRect *shr = new SizeHandleRect(this, it,strId, true); shr->setState(SelectionHandleOff); QPair pairone(strId,it); pairs.append(pairone); // MapList.insert(strId,it); m_handles.append(shr); } } //移除节点 void removeByHRect(SizeHandleRect *r) { for(int i=0;i pairs.removeAt(i); break; } } m_handles.removeAll(r); }

以及最重要的对坐标点的绘制重写

QPainterPath Polylines::shape() const { QPainterPath path; QPolygonF poly; for(int i=0;i return shape().controlPointRect(); } void Polylines::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { updatehandles(); Q_UNUSED(option); Q_UNUSED(widget); painter->setPen(pen()); painter->drawPolyline(GetPoints()); } 03 重写QGraphicsScene类修改事件执行

通过重写QGraphicsScene类来实现对多线段以及多线段节点的移除

//当不存在节点时删除 void QGraphicsSceneOverride::DelectPolyline() { foreach (QGraphicsItem *item, this->items()) { if(item->type() == Polylines::Type) { Polylines * poly=qgraphicsitem_cast(item); if(poly->m_handles.size()==0 && poly->pairs.size()==0) removeItem(poly); } } } //选中框中内容时删除 void QGraphicsSceneOverride::removeItemByRect(QRectF Rect) { foreach (QGraphicsItem *item, this->items()) { if(item->type() == SizeHandleRect::Type) { SizeHandleRect * rect=qgraphicsitem_cast(item); if(Rect.contains(rect->QPoLocats)) { if(rect->parentItem()!=NULL && rect->parentItem()->type() == Polylines::Type) { Polylines* line=qgraphicsitem_cast(rect->parentItem()); if(line->doubleClick) { line->removeByHRect(rect); removeItem(rect); DelectPolyline(); } } } } } } 04 重写QGraphicsView类 A. QGraphicsView实现指定位置放大缩小

根据鼠标所在的位置,放大缩小界面指定倍数 其中Dx,Dy为x,y坐标的放大缩小倍数,Pos为鼠标所在位置,缩小倍数值为0-1之间,放大倍数为1-2之间:

void QGraphicsViewOverride::Setwheelscale(double Dx,double Dy,QPoint Pos) { // 获取当前的鼠标所在的view坐标; QPoint prev_viewPos = Pos; // 获取当前鼠标相对于scene的位置; QPointF prev_scenePos = this->mapToScene(prev_viewPos); scale(Dx,Dy); this->scene()->setSceneRect(this->mapToScene(this->rect()).boundingRect()); //调整scene,使得scene和view一直,主要是为了排除掉scroll //获取缩放后的scene坐标 QPointF scenePos = this->mapToScene(prev_viewPos); //获取缩放前后的坐标差值,即为需要进行move的位移 QPointF disPointF = scenePos - prev_scenePos; // qDebug()sceneRect().width(), this->scene()->sceneRect().height()); this->scene()->update(); } B.QGraphicsView 上下左右方向键移动窗体内容显示

实现QGraphicsView显示内容的指定长度的滑动 Dx,Dy,x,y方向移动的距离

void QGraphicsViewOverride::SetMoveShow(double Dx,double Dy) { // this->scene()->setSceneRect(this->mapToScene(this->rect()).boundingRect()); //调整scene,使得scene和view一直,主要是为了排除掉scroll // coutsceneRect().x() scale(1/max,1/max); this->scene()->setSceneRect(this->mapToScene(this->rect()).boundingRect()); sceneF=this->scene()->itemsBoundingRect(); //中心对中心 QPointF viewTosceneCenter = this->mapToScene(QPoint(view.width()/2,view.height()/2)); QPointF sceneCenter(sceneF.width()/2,sceneF.height()/2); SetMoveShow(sceneCenter.x()-viewTosceneCenter.x(),sceneCenter.y()-viewTosceneCenter.y()); } } D. 带入重写的QGraphicsView事件中,实现功能

//滑轮滚动缩小屏幕内容

void QGraphicsViewOverride::wheelEvent(QWheelEvent *event) { if(event->delta()>0) { Setwheelscale(1.3,1.3,event->pos()); } else{ Setwheelscale(1 / 1.3, 1 / 1.3,event->pos()); } QGraphicsView::wheelEvent(event); // 执行QLineEdit类的默认事件处理 }

通过快捷键详细指定位置放大,上下左右滑动功能;

void QGraphicsViewOverride::keyReleaseEvent(QKeyEvent *event) { if(event->modifiers()==(Qt::ControlModifier) && event->key()==Qt::Key_F ) { Setwheelscale(1.9,1.9,PoMove); // QMessageBox::information(this,"Click", "Ctrl+F"); } else if(event->modifiers()==(Qt::ControlModifier) && event->key()==Qt::Key_G) { Setwheelscale(1 / 1.9,1 / 1.9,PoMove); } else if( event->key()==Qt::Key_Left) { // QMessageBox::information(this,"Click", "Key_Left"); SetMoveShow(5,0); } else if( event->key()==Qt::Key_Right) { SetMoveShow(-5,0); } else if( event->key()==Qt::Key_Up) { SetMoveShow(0,5); } else if( event->key()==Qt::Key_Down) { SetMoveShow(0,-5); } }


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

      专题文章
        CopyRight 2018-2019 实验室设备网 版权所有