一.前言
我的发,好久没有更新了,忙着考试去了,只剩下最后一科英语了,我赶紧来更新,哈哈,上节课我们的CAD项目还没有做完呢,OK,那就来咯!
我们上节课的成果:
上节课我们只实现了左边工具栏的功能,但是我们上面的工具栏的功能还没有进行实现,所以我们现在话不多说,直接开干!
二.缩放
1.逻辑
我们可以选择一个或者多个图形项
为了演示功能,我们如果选择的一个就对图形项进行缩放
如果选择的多个就对视图进行缩放
2.获取图形项选中的个数
void MainWindow::on_actionBig_triggered() { int count=scene->selectedItems().count(); }
看不懂?不存在的,看我的
**selectedItems()返回的一个装图形项指针的列表,所以我们可以用count()**来统计个数,哈哈.
3.获取图形项并放大
if(count==1) { auto item=scene->selectedItems().at(0); item->setScale(item->scale()+0.1); }
如果选中的个数为1,那么是对图形项进行操作!
刚刚说了**selectedItems()返回的是一个列表,所以可以用at()**来获取到图形项.
**setScale()**见名知意,这个就是用来缩放图形项的,此处是在原有的基础上进行缩放.
4.视图缩放
其他的情况我们就用视图的缩放
else { ui->graphicsView->scale(1.1,1.1); }
可以直接设置,不用像图形项一样获取原来的,因为看下图的翻译
5.完整代码
void MainWindow::on_actionBig_triggered() { int count=scene->selectedItems().count(); if(count==1) { auto item=scene->selectedItems().at(0); item->setScale(item->scale()+0.1); } else { ui->graphicsView->scale(1.1,1.1); } }
6.效果展示
这个是放大了的,可惜暂时还不会给你录动态图进行展示,哈哈.
7.缩小完整代码
解:由上同理可得,哈哈,想起了我的初中数学.
void MainWindow::on_actionSmall_triggered() { int count=scene->selectedItems().count(); if(count==1) { auto item=scene->selectedItems().at(0); item->setScale(item->scale()-0.1); } else { ui->graphicsView->scale(0.9,0.9); } }
运行结果就你们自己去试了!
三.旋转
1.图形项进行旋转
讲过的地方我就不讲了.
int count=scene->selectedItems().count(); if(count==1) { auto item=scene->selectedItems().at(0); item->setRotation(item->rotation()-30); }
还是在原有的基础上进行旋转.
2.视图的旋转
else { ui->graphicsView->rotate(-30); }
负号是逆时针进行旋转哦.
3.完整代码
void MainWindow::on_actionLeft_triggered() { int count=scene->selectedItems().count(); if(count==1) { auto item=scene->selectedItems().at(0); item->setRotation(item->rotation()-30); } else { ui->graphicsView->rotate(-30); } }
4.效果展示
5.右转代码
void MainWindow::on_actionRight_triggered() { int count=scene->selectedItems().count(); if(count==1) { auto item=scene->selectedItems().at(0); item->setRotation(item->rotation()+30); } else { ui->graphicsView->rotate(+30); } }
四.恢复
1.图形项复原
int count=scene->selectedItems().count(); if(count==1) { auto item=scene->selectedItems().at(0); item->setRotation(0); item->setScale(1.0); }
只需要将缩放倍数设置为1,旋转设置为0即可
2.视图复原
else { ui->graphicsView->resetTransform(); }
3.完整代码
void MainWindow::on_actionHuifu_triggered() { int count=scene->selectedItems().count(); if(count==1) { auto item=scene->selectedItems().at(0); item->setRotation(0); item->setScale(1.0); } else { ui->graphicsView->resetTransform(); } }
4.效果展示
自己去玩完.
五.前后置
1.设置z轴的值
void MainWindow::on_actionTop_triggered() { int count=scene->selectedItems().count(); if(count==1) { auto item=scene->selectedItems().at(0); item->setZValue(item->zValue()+1); } }
在原来的基础上对,z的值进行加1层!
2.后置代码
void MainWindow::on_actionButton_triggered() { int count=scene->selectedItems().count(); if(count==1) { auto item=scene->selectedItems().at(0); item->setZValue(item->zValue()-1); } }
自己去运行效果,我这里运行了,截图你们也看不出来!
六.组合和拆分
1.逻辑
我们将选中的多个图形项,放在一个图形项组中,相当于一个新的图像项.
2.创建图形项组
QGraphicsItemGroup* group=new QGraphicsItemGroup; scene->addItem(group);
因为组可以视为当个项,所有我们可以添加到场景.
3.图形项添加到组
for(int i=0;i<count;i++) { auto item=scene->selectedItems().at(0); item->setSelected(false); item->clearFocus(); group->addToGroup(item); }
当我们添加到组以后,原来的图像项的选中和聚焦状态都取消.
4.设置组的标识
group->setFlags(QGraphicsItem::ItemIsMovable| QGraphicsItem::ItemIsSelectable| QGraphicsItem::ItemIsFocusable); group->setZValue(ZVaule++); scene->clearSelection(); group->setSelected(true);
设置成可选中,可移动,可聚焦,同时设置z轴的值.
并将其设置为新的选中.
5.完整代码
void MainWindow::on_actionZuhe_triggered() { int count=scene->selectedItems().count(); if(count>1) { QGraphicsItemGroup* group=new QGraphicsItemGroup; scene->addItem(group); for(int i=0;i<count;i++) { auto item=scene->selectedItems().at(0); item->setSelected(false); item->clearFocus(); group->addToGroup(item); } group->setFlags(QGraphicsItem::ItemIsMovable| QGraphicsItem::ItemIsSelectable| QGraphicsItem::ItemIsFocusable); group->setZValue(ZVaule++); scene->clearSelection(); group->setSelected(true); } }
6.效果演示
嘿嘿嘿,自己就可以组合成任何的图像,哈哈哈.
7.拆分代码
获取的图形项,强转类型转换为图形项组然后进行拆分.
void MainWindow::on_actionChaifen_triggered() { int count=scene->selectedItems().count(); if(count==1) { auto group=(QGraphicsItemGroup*)scene->selectedItems().at(0); scene->destroyItemGroup(group); } }
8.效果展示
七.删除
1.删除代码
void MainWindow::on_actionDel_triggered() { int count=scene->selectedItems().count(); if(count>0) { for(int i=0;i<count;i++) { auto item=scene->selectedItems().at(0); scene->removeItem(item); } } }
八.双击编辑图形项颜色
1.逻辑
因为每个图形项的设置颜色方式,不一定相同
有的设置画刷,有的设置画笔,所以我们要对图形项的类型进行判断
因为有很多不同的图形项,所以我们可以用一个模板函数来传参来进行处理.
2.获取图形项的类型
void MainWindow::on_graphicsView_mouseDoubleClick(QPoint point) { int count =scene->selectedItems().count(); if(count==0) { return; } auto item=scene->selectedItems().at(0); switch (item->type()) { }
type()返回的一个整数,可以用switch来进行判断!
3.画刷模版函数
template <class T> void setBrushColor(T *item) { QColor color=item->brush().color(); color=QColorDialog::getColor(color,NULL,"选择填充颜色"); if(color.isValid()) { item->setBrush(QBrush(color)); } }
4.图形项类型的判断
switch (item->type()) { case QGraphicsRectItem::Type: { auto item2=qgraphicsitem_cast<QGraphicsRectItem*>(item); setBrushColor(item2); break; } case QGraphicsEllipseItem::Type: { auto item2=qgraphicsitem_cast<QGraphicsEllipseItem*>(item); setBrushColor(item2); break; } case QGraphicsPolygonItem::Type: { auto item2=qgraphicsitem_cast<QGraphicsPolygonItem*>(item); setBrushColor(item2); break; } }
这个几个都是一种类型的,调用模版函数设置画刷的颜色就可以!
5.画笔模版函数
template <class T> void setPenColor(T*item) { QPen pen; QColor color=item->pen().color(); color=QColorDialog::getColor(color,NULL,"选择填充颜色"); if(color.isValid()) { pen.setColor(color); item->setPen(pen); } }
6.线条图形项
因为不是用画刷进行填充颜色的,所以我们用画笔.
case QGraphicsLineItem::Type: { auto item2=qgraphicsitem_cast<QGraphicsLineItem*>(item); setPenColor(item2); break; }
7.文本图形项
case QGraphicsTextItem::Type: { auto item2=qgraphicsitem_cast<QGraphicsTextItem*>(item); QFont font; font=item2->font(); bool ok=false; font=QFontDialog::getFont(&ok,font,this,"选择字体"); if(ok) { item2->setFont(font); } break; }
用了一个字体对话框.
8.效果展示
非常的银杏.
九.按键微移
1.逻辑
我们上节课不写写了一个键盘事件嘛
现在我们可以根据键盘来对图形项进行操作
2.删除图形项
if(scene->selectedItems().count()!=1) { return; } auto item=scene->selectedItems().at(0); if(event->key()==Qt::Key_Delete) { scene->removeItem(item); }
就是键盘上的Delete键
3.旋转图形项
else if(event->key()==Qt::Key_Space) { item->setRotation(item->rotation()+10); }
Key_Space就是空格键.
4.放大,放小
else if(event->key()==Qt::Key_PageUp) { item->setScale(item->scale()+0.1); } else if(event->key()==Qt::Key_PageDown) { item->setScale(item->scale()-0.1); }
5.上下左右
else if(event->key()==Qt::Key_Left) { item->setX(item->x()-1); } else if(event->key()==Qt::Key_Right) { item->setX(item->x()+1); } else if(event->key()==Qt::Key_Up) { item->setY(item->y()-1); } else if(event->key()==Qt::Key_Down) { item->setY(item->y()+1); }
6.完整代码
void MainWindow::on_graphicsView_keyPress(QKeyEvent *event) { if(scene->selectedItems().count()!=1) { return; } auto item=scene->selectedItems().at(0); if(event->key()==Qt::Key_Delete) { scene->removeItem(item); } else if(event->key()==Qt::Key_Space) { item->setRotation(item->rotation()+10); } else if(event->key()==Qt::Key_PageUp) { item->setScale(item->scale()+0.1); } else if(event->key()==Qt::Key_PageDown) { item->setScale(item->scale()-0.1); } else if(event->key()==Qt::Key_Left) { item->setX(item->x()-1); } else if(event->key()==Qt::Key_Right) { item->setX(item->x()+1); } else if(event->key()==Qt::Key_Up) { item->setY(item->y()-1); } else if(event->key()==Qt::Key_Down) { item->setY(item->y()+1); } }
效果自己去用键盘玩哦!
十.鼠标移动
1.逻辑
当我们的鼠标进行移动的时候,我们就显示视图坐标和场景的坐标.
可通过视图坐标转到场景坐标.
同时,我们希望在状态栏中进行显示,所以我们需要在状态栏中,添加标签.
2.状态栏添加标签
我们原来讲过,状态栏添加组件,只能通过代码.
头文件中进行创建:
构造函数中,进行实现:
labView=new QLabel("视图坐标:"); labScene=new QLabel("场景坐标:"); labItem=new QLabel("图形项坐标:"); labInfo=new QLabel("图形项信息:"); labView->setMinimumWidth(150); labScene->setMinimumWidth(150); labItem->setMinimumWidth(150); labInfo->setMinimumWidth(150); this->statusBar()->addWidget(labView); this->statusBar()->addWidget(labScene); this->statusBar()->addWidget(labItem); this->statusBar()->addWidget(labInfo);
运行结果:
3.设置视图,场景坐标
void MainWindow::on_graphicsView_mouseMove(QPoint point) { labView->setText(QString::asprintf("视图坐标:%d,%d",point.x(),point.y())); QPointF pointScene=ui->graphicsView->mapToScene(point); labScene->setText(QString::asprintf("场景坐标:%.0f,%.0f",pointScene.x(),pointScene.y())); }
返回的浮点坐标.
4.效果展示
会随着我的鼠标移动而变化!
十一.鼠标单击
1.逻辑
当我们单击一个图形项的时候,就显示图形项坐标和图形项的信息.
2.通过场景坐标获取图形项
QPointF pointScene=ui->graphicsView->mapToScene(point); auto item=scene->itemAt(pointScene,ui->graphicsView->transform());
通过场景坐标得到场景中的项
3.场景坐标转换成图形项坐标
QPointF pointItem=item->mapFromScene(pointScene);//场景坐标转图形项坐标 labItem->setText(QString::asprintf("图形项坐标:%.0f,%.0f",pointItem.x(),pointItem.y()));
4.设置图形项的信息
还记得我们原理自己定义的数据嘛,就是setDate()
现在我们就可以拿出来用了.
labInfo->setText(item->data(ITEMINFO).toString()+"ITEMID:"+ item->data(ITEMID).toString());
这就是当年我们自定义数据的地方
现在就可以根据键来获取到,当时我们设置的图像名称和ID.
5.完整代码
void MainWindow::on_graphicsView_mousePress(QPoint point) { QPointF pointScene=ui->graphicsView->mapToScene(point); auto item=scene->itemAt(pointScene,ui->graphicsView->transform()); if(item) { QPointF pointItem=item->mapFromScene(pointScene);//场景坐标转图形项坐标 labItem->setText(QString::asprintf("图形项坐标:%.0f,%.0f",pointItem.x(),pointItem.y())); labInfo->setText(item->data(ITEMINFO).toString()+" ID:"+ item->data(ITEMID).toString()); } }
6.效果展示
OK,到这里,咱们这个项目就完结撒花啦,期待与你一起进步!
十二.总结
这就是基于QGraphicsView架构做的CAD项目,当然啦,还可以有更多的创意,你也试试看吧!
播下一颗种子…