当前位置:网站首页>diagramscene工程难点分析
diagramscene工程难点分析
2022-07-25 07:19:00 【荆楚闲人】
1.工程效果
本工程非常类似miscrosoft visio 软件的流程图组件:

2.工程存放路径
Examples\Qt-XX.XX.XX\widgets\graphicsview\diagramscene 目录下,XX.XX.XX为Qt的版本号,如:5.14.1。
3.工程难点分析
本工程有两个比较难懂的地方,其中一个代码如下:
void DiagramScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *mouseEvent)
{
if (line != nullptr && myMode == InsertLine) {
QList<QGraphicsItem *> startItems = items(line->line().p1());
if (startItems.count() && startItems.first() == line)
startItems.removeFirst();
QList<QGraphicsItem *> endItems = items(line->line().p2());
if (endItems.count() && endItems.first() == line)
endItems.removeFirst();
removeItem(line);
delete line;
//! [11] //! [12]
if (startItems.count() > 0 && endItems.count() > 0 &&
startItems.first()->type() == DiagramItem::Type &&
endItems.first()->type() == DiagramItem::Type &&
startItems.first() != endItems.first()) {
DiagramItem *startItem = qgraphicsitem_cast<DiagramItem *>(startItems.first());
DiagramItem *endItem = qgraphicsitem_cast<DiagramItem *>(endItems.first());
Arrow *arrow = new Arrow(startItem, endItem);
arrow->setColor(myLineColor);
startItem->addArrow(arrow);
endItem->addArrow(arrow);
arrow->setZValue(-1000.0);
addItem(arrow);
arrow->updatePosition();
}
}
//! [12] //! [13]
line = nullptr;
QGraphicsScene::mouseReleaseEvent(mouseEvent);
}第4~13行:检测拖动鼠标划线、当释放鼠标时,直线起始点和终止点下面的项对应的第一个项是不是直线对象自己,如果是则将直线对象从startItems 、endItems删除,因为拖动鼠标划线本意是想通过划线将两个非直线的item连接起来。直线自己连接自己无意义。
第16~28行:如果删除startItems 、endItems后,startItems 、endItems容器还不为空,证明startItems 、endItems中存放了非直线对象(item),则分别取出startItems 、endItems中的第一项,即取出两个非直线item,创建一个箭头对象(Arrow ),设置Arrow对象颜色、z次序,并将其设置到刚取出的非直线item对象中去。将箭头对象(Arrow )添加到场景并调用 Arrow::updatePosition()函数更新箭头对象(Arrow )位置。当调用 Arrow::updatePosition()时,会重新在这两个item之间创建一条直线对象。
另一个难点如下:
void Arrow::paint(QPainter *painter, const QStyleOptionGraphicsItem *,
QWidget *)
{
if (myStartItem->collidesWithItem(myEndItem))
return;
QPen myPen = pen();
myPen.setColor(myColor);
qreal arrowSize = 20;
painter->setPen(myPen);
painter->setBrush(myColor);
//! [4] //! [5]
QLineF centerLine(myStartItem->pos(), myEndItem->pos());
QPolygonF endPolygon = myEndItem->polygon();
QPointF p1 = endPolygon.first() + myEndItem->pos();
QPointF intersectPoint;
for (int i = 1; i < endPolygon.count(); ++i) {
QPointF p2 = endPolygon.at(i) + myEndItem->pos();
QLineF polyLine = QLineF(p1, p2);
QLineF::IntersectionType intersectionType =
polyLine.intersects(centerLine, &intersectPoint);
if (intersectionType == QLineF::BoundedIntersection)
break;
p1 = p2;
}
setLine(QLineF(intersectPoint, myStartItem->pos()));
//! [5] //! [6]
double angle = std::atan2(-line().dy(), line().dx());
QPointF arrowP1 = line().p1() + QPointF(sin(angle + M_PI / 3) * arrowSize,
cos(angle + M_PI / 3) * arrowSize);
QPointF arrowP2 = line().p1() + QPointF(sin(angle + M_PI - M_PI / 3) * arrowSize,
cos(angle + M_PI - M_PI / 3) * arrowSize);
arrowHead.clear();
arrowHead << line().p1() << arrowP1 << arrowP2;
//! [6] //! [7]
painter->drawLine(line());
painter->drawPolygon(arrowHead);
if (isSelected()) {
painter->setPen(QPen(myColor, 1, Qt::DashLine));
QLineF myLine = line();
myLine.translate(0, 4.0);
painter->drawLine(myLine);
myLine.translate(0,-8.0);
painter->drawLine(myLine);
}
}第14~26行:将myStartItem项位置点和myEndItem项位置点创建一个直线对象centerLine。将myEndItem项所在多边形的每个顶点取出并转为场景坐标,然后判断这个多边形每条边是否和centerLine相交,如果相交,则取出交点,且利用setLine函数,以交点为起始点,myStartItem项位置点为终点,更改Arrow类对象的直线。
第31~42:画出直线的箭头。
第43~49:当直线箭头被选中时,在上一步画出的直线的上边、下边画出1个像素画笔宽的虚线,这样给人的感觉是直线箭头被选中了。
经过这样操作后,就将myStartItem、myEndItem用直线箭头连接起来了,并能实现选中的感觉。
3 本工程存在的bug
本工程DiagramScene类的setLineColor、setTextColor、setItemColor函数存在bug,现以setLineColor为例子说明,其它类同。
void DiagramScene::setLineColor(const QColor &color)
{
myLineColor = color;
if (isItemChange(Arrow::Type)) {
Arrow *item = qgraphicsitem_cast<Arrow *>(selectedItems().first());
item->setColor(myLineColor);
update();
}
}isItemChange函数如下:
bool DiagramScene::isItemChange(int type) const
{
const QList<QGraphicsItem *> items = selectedItems();
const auto cb = [type](const QGraphicsItem *item) { return item->type() == type; };
return std::find_if(items.begin(), items.end(), cb) != items.end();
}setLineColor函数的意思就是看看选中的项中是否存在箭头类型的项,如果存在,则取出选中项列表中的第一个项,并将其设置为setLineColor函数参数的颜色,问题是:选中项列表中的第一个项可能不是箭头类型项,即如下代码:
Arrow *item = qgraphicsitem_cast<Arrow *>(selectedItems().first());返回的item可能为nullptr,即 qgraphicsitem_cast<Arrow *>转换失败,导致item为nullptr,从而导致后面的代码崩溃。可以试着左边一个方框,右边一个方框,然后这两个方框用直线箭头连接,然后先选中左边的方框,再选中箭头,此时就崩溃了。
边栏推荐
- The idea of the regular crawler of the scratch
- Incremental crawler in distributed crawler
- Kubernates-1.24.2 (latest version) + containerd + nexus
- File operation-
- Scavenging vultures or woodpeckers? How to correctly understand short selling
- CEPH in hand, I have!
- Paddlepaddle 34 adjust the layer structure and forward process of the model (realize the addition, deletion, modification and forward modification of the layer)
- 如何在KVM环境中使用网络安装部署多台虚拟服务器
- Electronic Association C language level 2 60, integer parity sort (real question in June 2021)
- 【云原生】原来2020.0.X版本开始的OpenFeign底层不再使用Ribbon了
猜你喜欢

"Game illustrated book": a memoir dedicated to game players

一日千里,追风逐月 | 深势科技发布极致加速版分子对接引擎Uni-Docking

Summary of differences between data submission type request payload and form data

LeetCode118. 杨辉三角

【云原生】原来2020.0.X版本开始的OpenFeign底层不再使用Ribbon了

Alibaba cloud image address & Netease cloud image

Leetcode sword finger offer brush question notes

Ideal L9, can't cross a pit on the road?

Security compliance, non-stop discounts! High quality travel service, "enjoy the road" for you

PADS导出gerber文件
随机推荐
The relationship between Informatics, mathematics and Mathematical Olympiad (July 19, 2022) C
[computer explanation] NVIDIA released geforce RTX Super Series graphics cards, and the benefits of game players are coming!
error: redefinition of
Rambus announces ddr5 memory interface chip portfolio for data centers and PCs
New functions of shixizhi are online. These new functions are online in June. Can you use them?
【terminal】x86 Native Tools Command Prompt for VS 2017
Yolov7 model reasoning and training its own data set
北京内推 | 微软STCA招聘NLP/IR/DL方向研究型实习生(可远程)
10 key points and 5 measures for good project management
【程序员2公务员】关于体制调研的一些常见问题总结
150. Evaluation of inverse Polish expression
Learn no when playing 10. Is enterprise knowledge management too boring? Use it to solve!
[300 + selected interview questions from big companies continued to share] big data operation and maintenance sharp knife interview question column (V)
JS cannot get content disposition in headers
From the era of portal to the era of information flow, good content has been ignored?
Price reduction, game, bitterness, etc., vc/pe rushed to queue up and quit in 2022
Traffic is not the most important thing for the metauniverse. Whether it can really change the traditional way of life and production is the most important
Purpose of SQL square brackets
Scavenging vultures or woodpeckers? How to correctly understand short selling
Hierarchical reinforcement learning: a comprehensive survey