[Qt5] QGraphics图形视图框架概述(Item、Scene和View)

  • 📢博客主页:https://blog.csdn.net/weixin_43197380
  • 📢欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正!
  • 📢本文由 Loewen丶原创,首发于 CSDN,转载注明出处🙉
  • 📢现在的付出,都会是一种沉淀,只为让你成为更好的人✨


📢 图形视图框架的介绍

  在 Qt 框架内的许多模块,类和子框架下,有一块专门用于简化图形处理的工具,称为图形视图框架。 它包含许多类,几乎所有的类都以QGraphics开头,并且所有这些类都可用于处理构建计算机视觉应用时可能遇到的大多数图形任务。 图形视图框架将所有可能的对象简单地分为三个主要类别,即场景类(QGraphicsScene)、视图类(QGraphicsView)和图元类(QGraphicsItem),统称为“三元素”。随之而来的架构允许轻松地添加,删除,修改以及显示图形对象。

  • 视图(QGraphicsView小部件):用于可视化和显示QGraphicsScene的内容。 它还负责将事件传播到QGraphicsScene。 这里要注意的重要一点是QGraphicsSceneQGraphicsView都具有不同的坐标系。 可以猜到,如果放大,缩小或进行不同的相似变换,则场景上的位置将不同。 QGraphicsSceneQGraphicsView都提供了转换彼此适合的位置值的功能。
  • 场景(QGraphicsScene类):管理项目(QGraphicsItem)的实例(其子类),包含它们,并将事件(例如,鼠标单击、移动等)传播到项目中。一个场景可以通过多个视图表现,一个场景也可以包括多个几何图形。
  • 图形项目(QGraphicsItem及其子类)这些项目(QGraphicsItem)子类的实例是QGraphicsScene中包含的项目。 它们可以是线,矩形,图像,文本等

🌺 视图类 — QGraphicsView

  QGraphicsView类是 Qt 窗口小部件类,可以将其放置在窗口上以显示QGraphicsScene,该窗口本身包含许多QGraphicsItem子类和/或窗口小部件。 与QGraphicsScene类相似,该类还提供大量函数,方法和属性来处理图形的可视化部分。 我们将审核以下列表中的一些最重要的函数,然后我们将学习如何对QGraphicsView进行子类化并将其扩展为在我们全面的计算机视觉应用中具有若干重要功能,例如放大,缩小, 项目选择等。因此,这是我们在计算机视觉项目中需要的QGraphicsView类的方法和成员:

  • alignmentsetAlignment函数可用于设置场景在视图中的对齐方式。 重要的是要注意,只有当视图可以完全显示场景,即视图不需要滚动条时,这才具有可见效果。一般当场景大于视图会出现滚动条,是不能通过setAlignment()函数来设置场景在视图中的对齐方式的。

    左对齐Qt::AlignLeft ; 向上对齐Qt::AlignTop ; 中心对齐Qt::AlignCenter
    eg:setAlignment(Qt::AlignLeft | Qt::AlignTop);
    
  • dragModesetDragMode函数可用于获取和设置视图的拖动模式。 这是视图的最重要函数之一,它可以决定在视图上单击并拖动鼠标左键时会发生什么。我们将使用QGraphicsView::DragMode枚举设置不同的拖动模式。

    QGraphicsView::NoDrag:忽略鼠标事件,不可以拖动。
    QGraphicsView::ScrollHandDrag:光标变为手型,可以拖动场景进行移动。
    QGraphicsView::RubberBandDrag:使用橡皮筋效果,进行区域选择,可以选中一个区域内的所有图形项。
    
  • isInteractivesetInteractive函数允许检索和修改视图的交互行为。 交互式视图会响应鼠标和键盘(如果已实现),否则,所有鼠标和键盘事件都将被忽略,并且该视图只能用于查看并且不能与场景中的项目进行交互。

  • optimizationFlagssetOptimizationFlagsrenderHintssetRenderHintsviewportUpdateModesetViewportUpdateMode函数分别用于获取和设置与视图的性能和渲染质量有关的参数。 在下面的示例项目中,我们将在实践中看到这些函数的用例。

  • dragMode设置为RubberBandDrag模式的情况下,可以使用rubberBandSelectionModesetRubberBandSelectionMode函数设置视图的项目选择模式。 可以设置以下内容,它们是Qt::ItemSelectionMode枚举中的条目:

    Qt::ContainsItemShape、Qt::IntersectsItemShape、Qt::ContainsItemBoundingRect、Qt::IntersectsItemBoundingRect
    
  • sceneRectsetSceneRect函数可用于获取和设置视图中场景的可视化区域。 显然,该值不必与QGraphicsScene类的sceneRect相同。

  • centerOn函数可用于确保特定点或项目位于视图中心。

  • ensureVisible函数可用于将视图滚动到特定区域(具有给定的边距)以确保它在视图中。 此函数适用于点,矩形和图形项目。

  • fitInView函数与centerOnensureVisible非常相似,但主要区别在于,该函数还使用给定的宽高比处理参数缩放视图的内容以适合视图。 以下:

    Qt::IgnoreAspectRatio、Qt::KeepAspectRatio、Qt::KeepAspectRatioByExpanding
    eg:fitInView(m_view->sceneRect(), Qt::KeepAspectRatio);   //场景大小适应视图View大小  
    
  • itemAt函数可用于在视图中的特定位置检索项目。

  我们已经了解到场景中的每个项目和场景中的每个项目都有各自的坐标系,我们需要使用映射函数将位置从一个位置转换到另一个位置,反之亦然。 视图也是如此。 视图还具有自己的坐标系,主要区别在于视图中的位置和矩形等实际上是根据像素进行测量的,因此它们是整数,但是场景和项目的位置使用实数,等等。 这是由于以下事实:场景和项目在视图上被查看之前都是逻辑实体,因此所有实数都将转换为整数,而整个场景(或部分场景)准备在屏幕上显示。下图可以帮助您更好地理解这一点:
在这里插入图片描述

  • mapFromScenemapToScene函数可用于在场景坐标系之间转换位置。与前面提到的一致,mapFromScene函数接受实数并返回整数值,而mapToScene函数接受整数并返回实数。稍后我们将开发视图的缩放功能时,将使用这些函数。
  • items函数可用于获取场景中的项目列表。
  • render函数对于执行整个视图或其一部分的渲染很有用。该函数的用法与QGraphicsScene中的render完全相同,只是此函数在视图上执行相同的功能。
  • rubberBandRect函数可用于获取橡皮筋选择的矩形。如前所述,这仅在拖动模式设置为rubberBandSelectionMode时才有意义。
  • setScenescene函数可用于设置和获取视图场景。
  • setMatrix,setTransform,transform,rotate,scale,shear和translate函数都可以用于修改或检索视图的几何特性。

  与QGraphicsSceneQGraphicsItem类相同,QGraphicsView还提供了许多相同的受保护虚拟成员,可用于进一步扩展视图的功能。 现在,我们将对平时应用QGraphicsView扩展类时经常使用到的功能:

1、缩放与旋转

QGraphicsView::scale(xScale, yScale);//在分别在x,y方向上缩放xScale,yScale倍。若为1.0倍,则不进行缩放。
QGraphicsView::rotate(90);//顺时针旋转90度

  功能实现:

//重写QGraphicsView类中滑轮事件,完成缩放功能。MyGraphicsView为继承QGraphicsView的子类
void MyGraphicsView::wheelEvent(QWheelEvent *event) 
{ 
	// 获取当前鼠标相对于view的位置;
	QPointF cursorPoint = event->pos();
	// 获取当前鼠标相对于scene的位置;
	QPointF scenePos = this->mapToScene(QPoint(cursorPoint.x(), cursorPoint.y()));	
	// 获取view的宽高;
	qreal viewWidth = this->viewport()->width();
	qreal viewHeight = this->viewport()->height();
	// 获取当前鼠标位置相当于view大小的横纵比例;
	qreal hScale = cursorPoint.x() / viewWidth;
	qreal vScale = cursorPoint.y() / viewHeight;
	// 当前放缩倍数;
	//qreal scaleFactor = this->matrix().m11();
	int wheelDeltaValue = event->delta();
	// 向上滚动,放大
	if (wheelDeltaValue > 0)
	{
		this->scale(1.4, 1.4);
	}
	// 向下滚动,缩小;
	else
	{
		this->scale(1/ 1.4, 1 / 1.4);;
	}		
	// 将scene坐标转换为放大缩小后的坐标;
	QPointF viewPoint = this->matrix().map(scenePos);
	// 通过滚动条控制view放大缩小后的展示scene的位置;
	this->horizontalScrollBar()->setValue(int(viewPoint.x() - viewWidth * hScale));
	this->verticalScrollBar()->setValue(int(viewPoint.y() - viewHeight * vScale));
} 

2、其他事件传递

  在上面我们看到必须在事件函数的最后将event参数传递出去,才能执行默认的事件操作。其实不止上面那一种情况,在图形视图框架中,鼠标键盘等事件是从视图View进入的,视图View将它们传递给场景Scene,场景Scene再将事件传递给该点的图形项Item,如果该点有多个图形项,那么就传给最上面的图形项。所以要想使这个事件能一直传播下去,我们就需要在重新实现事件处理函数时,在其最后将event参数传给默认的事件处理函数。比如我们重写了场景的键盘按下事件处理函数,那么我们就在该函数的最后写上QGraphicsView::keyPressEvent(event);

  除了像上面那样通过直接重写QGraphicsView的虚函数的方式来实现事件的传递之外,还可以通过事件过滤器eventFilter的方式来实现:

MyGraphicsView::MyGraphicsView(QWidget *parent)
	:QGraphicsView(parent)
{
    this->viewport()->installEventFilter(this);	
}

bool MyGraphicsView::eventFilter(QObject *obj, QEvent *event)
{
    /*
    实现方式
    */
    return false;			//返回false表示不过滤
}

🌺 场景类 — QGraphicsScene

  场景分为3层:分别是背景层、图形项层、前景层。我们绘制的图形item都是放在图形项层的:

场景绘制顺序:背景层->图像项层->场景层

  QGraphicsScene类提供了处理多个图形项(QGraphicsItem)所需的几乎所有方法。其主要作用是作为一个容器放置图元Item,本身是不可见的,必须关联到至少一个QGraphicsView。这两者的关系就画布和画板的关系,View是画板,负责显示;Scene是画布,负责存储图形数据。所以从这个角度出发,我们可以这样认为,一个Scene可以关联到多个View,就好比一份画布贴到不同的画板上来被外界所看到一样。

  • addEllipseaddLineaddRectaddPolygon函数可以从它们的名称中猜测出来,可以用来向场景添加通用的几何形状。 它们中的一些提供了重载函数,以便于输入参数。 创建并添加到场景时,上述每个函数都会返回其对应的QGraphicsItem子类实例(如下所示)。返回的指针可以保留,以后可用于修改,删除或以其他方式使用该项目:

    QGraphicsEllipseItem
    QGraphicsLineItem
    QGraphicsRectItem
    QGraphicsPolygonItem
    

  使用示例:

scene.addEllipse(-100.0, 100.0, 200.0, 100.0, 
                QPen(QBrush(Qt::SolidPattern), 2.0), 
                QBrush(Qt::Dense2Pattern)); 

scene.addLine(-200.0, 200, +200, 200, 
              QPen(QBrush(Qt::SolidPattern), 5.0)); 
scene.addRect(-150, 150, 300, 140); 

QVector<QPoint> points; 
points.append(QPoint(150, 250)); 
points.append(QPoint(250, 250)); 
points.append(QPoint(165, 280)); 
points.append(QPoint(150, 250)); 
scene.addPolygon(QPolygon(points)); 

  代码结果:
在这里插入图片描述

  • addPath函数可用于将QPainterPath与给定的QPenQBrush添加到场景中。QPainterPath类可用于记录绘画操作,类似于我们在QPainter中看到的操作,并在以后使用它们。另一方面,QPenQBrush类具有不言自明的标题。addPath函数返回一个指向新创建的QGraphicsPathItem实例的指针。
  • addSimpleTextaddText函数可用于将纯文本和带格式的文本添加到场景中。 它们分别返回指向QGraphicsSimpleTextItemQGraphicsTextItem的指针。

  使用示例:

QGraphicsScene *pScene = new QGraphicsScene();
QGraphicsView  *pView  = new QGraphicsView();
//1、将项目Item添加到场景Scene中,即构造一个QGraphicsScene的对象。
pScene->addText("Hello, world!");//添加文本图形项
//2、使用QGraphicsView::setScene()将Scene加入到View中,视图View的可视化需要场景Scene的加入来进行实现。
pView->setScene(pScene);

pView->show();

  代码结果:
在这里插入图片描述
  图形项Item添加到场景Scene中有两种方式,一是通过调用便利函数addEllipse()、addLine()、addPath()、addPixmap()、addPolygon()、addRect()或addText()等,这些函数都返回指向新添加项的指针。二是调用addIitem()添加现有的QGraphicsItem对象(主要是自定义继承的QGraphicsItem);使用这些函数添加的项目的尺寸是相对于项目的坐标系的,并且项目位置在场景中初始化为(0,0)

  那么,上面addText("Hello, world!") 则可以换转成方式二:通过调用addIitem()添加现有的QGraphicsItem对象:

QGraphicsTextItem *item = new QGraphicsTextItem("Hello, world!");
scene.addItem(item);
  • addWidget函数可用于将 Qt 小部件添加到场景。 除了某些特殊的小部件(即设置了Qt::WA_PaintOnScreen标志的小部件或使用外部库(例如OpenGLActive-X绘制的小部件))之外,您还可以将其他任何小部件添加到场景中,这为使用交互式图形项创建场景提供了巨大的力量。下面举一个简短的示例:将场景和QWidget窗体绑定
if (m_view == nullptr){
	m_view = new MF_GraphicsView(_parent);
}
if (m_scene == nullptr){
	m_scene = new MF_GraphicsScene();
}
m_scene->setSceneRect(m_view->pos().x(), m_view->pos().y(), 2040, 2040);	 //设置场景大小	
m_view->setScene(m_scene);      //将场景绑定到视图上	
if (ui.widget->layout() == nullptr)
{
	QGridLayout* _layout = new QGridLayout();
	_layout->setMargin(0);
	ui.widget->setLayout(_layout);
}
ui.widget->layout()->addWidget(m_view);
  • setBackgroundBrushbackgroundBrushsetForegroundBrushforegroundBrush函数允许访问负责刷新场景的backgroundforegroundQBrush类。
  • fontsetFont函数可用于获取或设置QFont类,以确定场景中使用的字体。
  • 当我们想要定义最小尺寸来决定某项是否适合绘制(渲染)时,minimumRenderSizesetMinimumRenderSize函数非常有用。
  • sceneRectsetSceneRect函数可用于指定场景的边界矩形。默认情况下,场景的大小是无限的。图形项可以放到场景的任何位置。这导致场景想要搜索所有的图形项,然后确定出其边界,这是十分费时的。所以如果要操作一个较大的场景,我们应该给出它的边界矩形。设置边界矩形,可以使用setSceneRect()函数。上面Hello world例子加入场景边界矩形的方式如下:
QGraphicsView *pView = new QGraphicsView();
QGraphicsScene *pScene = new QGraphicsScene();
pScene->setSceneRect(0, 0, pView->width(), pView->height());

pScene->addText("Hello, world!");//添加文本图形项
pView->setScene(pScene);

pView->show();
  • stickyFocussetStickyFocus函数可用于启用或禁用场景的粘滞聚焦模式。 如果启用了粘滞聚焦,则单击场景中的空白区域不会对聚焦的项目产生任何影响; 否则,将仅清除焦点,并且不再选择选定的项目。
  • collidingItems是一个非常有趣的功能,可用于简单地确定某项是否与其他任何项共享其区域的某个部分(或发生碰撞)。 您需要将QGraphicsItem指针与Qt::ItemSelectionMode一起传递,您将获得与项目发生冲突的QGraphicsItem实例的QList
  • createItemGroupdestroyItemGroup函数可用于创建和删除QGraphicsItemGroup类实例。 QGraphicsItemGroup基本上是另一个QGraphicsItem子类(如QGraphicsLineItem等),可用于将一组图形项分组并因此表示为单个项。
  • hasFocus,setFocus,focusItem和setFocusItem函数均用于处理图形场景中当前聚焦的项目。
  • 返回与sceneRect.width()sceneRect.height()相同值的widthheight可用于获取场景的宽度和高度。 请务必注意,这些函数返回的值的类型为qreal(默认情况下与double相同),而不是integer,因为场景坐标在像素方面不起作用。 除非使用视图绘制场景,否则将其上的所有内容都视为逻辑和非视觉对象,而不是视觉对象,这是QGraphicsView类的领域。
  • 在某些情况下,与update()相同的invalidate可用于请求全部或部分重绘场景。 类似于刷新函数。
  • itemAt函数可用于在场景中的某个位置找到指向QGraphicItem的指针。
  • item返回添加到场景的项目列表。 基本上是QGraphicsItemQList
  • itemsBoundingRect可用于获取QRectF类,或仅获取可包含场景中所有项目的最小矩形。 如果我们需要查看所有项目或执行类似操作,此函数特别有用
  • mouseGrabberItem可用于获取当前单击的项目,而无需释放鼠标按钮。 此函数返回一个QGraphicsItem指针,使用它我们可以轻松地向场景添加“拖动和移动”或类似功能。
  • removeItem函数可用于从场景中删除项目。 此函数不会删除该项目,并且调用方负责任何必需的清理。
  • selectedItems,selectionArea和setSelectionArea函数结合使用时,可以帮助处理一个或多个项目选择。 通过提供Qt::ItemSelectionMode枚举,我们可以基于完全选择一个框中的项目或仅对其一部分进行选择,等等。 我们还可以为该函数提供Qt::ItemSelectionOperation枚举条目,以增加选择或替换所有先前选择的项目。
  • sendEvent函数可用于将QEvent类(或子类)发送到场景中的项目。
  • stylesetStyle函数用于设置和获取场景样式。
  • update函数可用于重绘部分或全部场景。 当场景的视觉部分发生变化时,最好将此函数与QGraphicsScene类发出的变化信号结合使用。
  • views函数可用于获取QList类,其中包含用于显示(或查看)此场景的QGraphicsView小部件。

   除了先前的现有方法外,QGraphicsScene提供了许多虚拟函数,可用于进一步自定义和增强QGraphicsScene类的行为以及外观。 因此,与其他任何类似的 C++ 类一样,您需要创建QGraphicsScene的子类,并只需添加这些虚拟函数的实现即可。 实际上,这是使用QGraphicsScene类的最佳方法,它为新创建的子类提供了极大的灵活性:

  • 可以覆盖dragEnterEvent,dragLeaveEvent,dragMoveEvent和dropEvent函数,以向场景添加拖放功能。 请注意,这与前面示例中将图像拖放到窗口中所做的非常相似。 这些事件中的每一个都提供足够的信息和参数来处理整个拖放过程。
  • 如果我们需要在整个场景中添加自定义背景或前景,则应覆盖drawBackgrounddrawForeground函数。 当然,对于简单的背景或前景绘画或着色任务,我们可以简单地调用setBackgroundBrushsetForegroundBrush函数,而跳过这些函数。
  • mouseDoubleClickEvent,mouseMoveEvent,mousePressEventmouseReleaseEvent和wheelEvent函数可用于处理场景中的不同鼠标事件。 例如,在项目中为场景添加放大和缩小功能时,可通过重写wheelEvent函数来实现。
  • QGraphicsScene的是从QGraphicsView传播事件。要将事件发送到场景,可以构造继承QEvent的事件,然后使用QApplication::SendEvent()发送它。event()负责将事件分派给各个项目。一些常见事件由方便的事件处理程序处理。例如,按键事件由keypressEvent()处理,鼠标按键事件由mousePressEvent()处理。

🌺 图元类 — QGraphicsItem

  它是场景中各个图元的基类,在它的基础上可以继承出各种图元类,即使您可以将其子类化并创建自己的图形项(自己重新实现绘制函数),Qt也会提供一组子类,这些子类可用于大多数(如果不是全部)日常图形任务。 以下是这些子类:

QGraphicsEllipseItem     //椭圆
QGraphicsLineItem        //直线
QGraphicsPathItem
QGraphicsPixmapItem
QGraphicsPolygonItem     //多边形
QGraphicsRectItem        //矩形
QGraphicsSimpleTextItem   
QGraphicsTextItem        //文本图元
  • QGraphicsItem主要有以下功能:
    处理鼠标按下、移动、释放、双击、悬停、滚轮和右键菜单事件。
    处理键盘输入事件。
    处理拖拽事件。
    分组。
    碰撞检测。

  如前所述,QGraphicsItem提供了许多函数和属性来处理图形应用中的问题和任务。 在本文中,我们将介绍QGraphicsItem中一些最重要的成员,这些成员因此可以通过熟悉前面提到的子类来帮助我们:

  • acceptDropssetAcceptDrops函数可用于使项目接受拖放事件。 请注意,这与我们在前面的示例中已经看到的拖放事件非常相似,但是这里的主要区别是项目本身可以识别拖放事件。
  • acceptHoverEventssetAcceptHoverEventsacceptTouchEventssetAcceptTouchEventsacceptedMouseButtonssetAcceptedMouseButtons函数均处理项目交互及其对鼠标单击的响应等。 这里要注意的重要一点是,一个项目可以根据Qt::MouseButtons枚举设置来响应或忽略不同的鼠标按钮。 这是一个简单的例子:
QGraphicsRectItem *item = new QGraphicsRectItem(0, 0, 100, 100, this); 
item->setAcceptDrops(true); 
item->setAcceptHoverEvents(true); 
item->setAcceptedMouseButtons( Qt::LeftButton | 
                               Qt::RightButton | 
                               Qt::MidButton); 
  • boundingRegion函数可用于获取描述图形项区域的QRegion类。 这是一项非常重要的函数,因为它可用于获取需要绘制(或重绘)项目的确切区域,并且与项目的边界矩形不同,因为简单地说,该项目可能仅覆盖其边界矩形的一部分,如直线等。 有关更多信息,请参见以下示例。
  • 在计算项目的boundingRegion函数时,boundingRegionGranularitysetBoundingRegionGranularity函数可用于设置和获取粒度级别。 从这个意义上讲,粒度是0和1之间的实数,它对应于计算时的预期详细程度:
QGraphicsEllipseItem *item = new QGraphicsEllipseItem(0, 0, 100, 100); 
scene.addItem(item); 
item->setBoundingRegionGranularity(g); // 0 , 0.1 , 0.75 and 1.0 
QTransform transform; 
QRegion region = item->boundingRegion(transform); 
QPainterPath painterPath; 
painterPath.addRegion(region); 
QGraphicsPathItem *path = new QGraphicsPathItem(painterPath); 
scene.addItem(path); 

  在前面的代码中,如果将g替换为0.0,0.1,0.75和1.0,则会得到以下结果。 显然,0的值(默认粒度)导致单个矩形(边界矩形),这不是准确的估计。 随着级别的增加,我们得到了覆盖图形形状和项目的更准确的区域(基本上是矩形集):

在这里插入图片描述

  • childItems函数可用于获取填充有QGraphicsItem类的QList,这些类是此项的子级。 将它们视为更复杂项目的子项目。

  • childrenBoundingRectboundingRectsceneBoundingRect函数可用于检索QRectF类,其中包含该项目的子项bounding rect,该项目本身和场景。

  • clearFocussetFocushasFocus函数可用于删除,设置和获取该项目的聚焦状态。 具有焦点的项目接收键盘事件。

  • collidesWithItemcollidesWithPathcollidingItems函数可用于检查此项目是否与任何给定项目发生冲突,以及该项目与之碰撞的项目列表。

  • contains函数获取一个点的位置(准确地说是QPointF类),然后检查此项是否包含该点。

  • cursorsetCursorunsetCursorhasCursor函数对于设置,获取和取消设置此项的特定鼠标光标类型很有用。 您还可以在取消设置之前检查项目是否有任何设置的光标。 设置后,如果鼠标光标悬停在该项目上,则光标形状变为一组。

  • hideshowsetVisibleisVisibleopacitysetOpacityeffectiveOpacity函数均与商品的可见性(和不透明度)有关。 所有这些函数都具有不言自明的名称,唯一值得注意的是effectiveOpacity,它可能与此项的不透明度相同,因为它是基于该项及其父项的不透明度级别计算的。 最终,effectiveOpacity是用于在屏幕上绘制该项目的不透明度级别。

  • flagssetFlagssetFlag函数可用于获取或设置此项的标志。 通过标志,我们基本上是指QGraphicsItem::GraphicsItemFlag枚举中各项的组合。 这是一个示例代码:

item->setFlag(QGraphicsItem::ItemIsFocusable, true); 
item->setFlag(QGraphicsItem::ItemIsMovable, false);

  重要的是要注意,当我们使用setFlag函数时,所有以前的标志状态都会保留,并且此函数中只有一个标志会受到影响。 但是,当我们使用setFlags时,基本上所有标志都会根据给定的标志组合进行重置。

  • 当我们想要更改从场景中获取鼠标和键盘事件的项目时,grabMouse,grabKeyboardungrabMouseungrabKeyboard方法很有用。 显然,使用默认实现时,一次只能抓取一个项目,除非另一个抓取项目或者项目本身不变形或被删除或隐藏,否则抓取器将保持不变。 正如本章前面所看到的,我们总是可以使用QGraphicsScene类中的mouseGrabberItem函数来获取抓取器项目。

  • setGraphicsEffectgraphicsEffect函数可用于设置和获取QGraphicsEffect类。 这是一个非常有趣且易于使用的函数,但功能强大,可用于向场景中的项目添加过滤器或效果。QGraphicsEffectQt中所有图形效果的基类。 您可以将其子类化并创建自己的图形效果或过滤器,也可以仅使用提供的Qt图形效果之一。 目前,Qt中有一些图形效果类,您可以自己尝试一下:

    QGraphicsBlurEffect
    QGraphicsColorizeEffect
    QGraphicsDropShadowEffect
    QGraphicsOpacityEffect
    

  现在,让我们继续进行QGraphicsItem类中的其余函数和属性:

  • 当我们想将一个项目添加到组中或获取包含该项目的组类时,groupsetGroup函数非常有用,只要该项目属于任何组。 QGraphicsItemGroup是负责处理组的类。
  • isAncestorOf函数可用于检查该项目是否为任何给定其他项目的父项(或父项的父项,依此类推)。
  • 可以设置setParentItemparentItem并检索当前项目的父项目。 一个项目可能根本没有任何父项,在这种情况下,parentItem函数将返回零。
  • isSelectedsetSelected函数可用于更改项目的所选模式。 这些函数与setSelectionArea和您在QGraphicsScene类中了解的类似函数密切相关。
  • mapFromItemmapToItemmapFromParentmapToParentmapFromScenemapToScenemapRectFromItemmapRectToScenemapRectFromParentmapRectToParentmapRectFromScenemapRectToScene函数 ,所有这些函数甚至都具有更多方便的重载函数,构成了一长串函数,这些函数用于从或向其进行基本映射,或者换句话说,可用于从场景,另一项或父对象到场景的坐标转换。

  与我们在QGraphicsScene类中看到的类似,QGraphicsItem类还包含许多受保护的虚函数,这些函数可以重新实现,主要用于处理传递到场景项上的各种事件。 以下是一些重要且非常有用的示例:

contextMenuEvent
dragEnterEvent,dragLeaveEvent,dragMoveEvent,dropEvent
focusInEvent,focusOutEvent
hoverEnterEvent,hoverLeaveEvent,hoverMoveEvent
keyPressEvent,keyReleaseEvent
mouseDoubleClickEvent,mouseMoveEvent,mousePressEvent,mouseReleaseEvent,wheelEvent

📃 总结

    QGraphicsView的作用相当于画板QGraphicsScene等效于画布QGraphicsItem为画布上的画

    映射到Qt中就是:

  • 拿出画板,订上一张画布:UI中添加了一个QGraphicsView后,需要往其中添加QGraphicsScene,可以添加好几张画布;
  • 拿起笔,在画布上作画:往QGraphicsScene上添加各式各样的QGraphicsItemQGraphicsItem有很多种,最常用的是QGraphicsPixmapItem,也就是贴图到画布上;使用QPainter,可以自己亲自画线。

    大致过程就如上所述,因此,完成一幅图片的显示需要三个步骤:

  1. Pixmap添加至QGraphicsPixmapItem
  2. QGraphicsPixmapItem添加至QGraphicsScene
  3. QGraphicsScene添加至QGraphicsView

戳戳小手帮忙点个免费的赞和关注吧,嘿嘿。
  • 65
    点赞
  • 141
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 42
    评论
背景技术 Qt是一个跨平台的C++应用程序开发框架,主要用于开发图形用户界面(GUI)应用程序。Qt提供了一个名为QGraphicsView图形框架,可以用于创建高性能、可交互的2D图形场景。WPF是Microsoft .NET Framework中的一个GUI框架,它提供了一种可扩展的应用程序开发模型,使得开发人员可以更方便地创建Windows应用程序、网页浏览器插件等。 技术方案 本专利提供了一种将Qt QGraphicsView图形框架嵌入WPF控件的方法。该方法可以实现Qt QGraphicsView的高性能、可交互的2D图形场景显示在WPF应用程序中。 具体实现步骤如下: 1.在WPF应用程序中创建一个自定义控件,该控件继承自System.Windows.Forms.Integration.ElementHost类。 2.在自定义控件中创建一个QGraphicsView对象,并将其设置为子控件。 3.将QGraphicsView对象的viewport设置为WPF控件的句柄,这样就可以将QGraphicsView渲染的2D图形场景显示在WPF应用程序中。 4.通过调用QGraphicsView对象的API实现2D图形场景的交互,例如缩放、平移、旋转等操作。 5.将WPF应用程序与Qt应用程序连接起来,实现数据的双向传输。 优势和应用 本专利提供了一种将Qt QGraphicsView图形框架嵌入WPF控件的方法,具有如下优势: 1.实现了高性能、可交互的2D图形场景在WPF应用程序中的显示。 2.可以方便地实现2D图形场景的交互操作,提高用户体验。 3.可以实现WPF应用程序与Qt应用程序之间的数据传输,方便数据共享。 本专利的应用范围广泛,例如在工业自动化、图像处理、CAD软件等领域都可以应用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 42
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

丶布布

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值