如何使QGraphicsItem不随QGraphicsView放大缩小而改变大小
来源:互联网 发布:西班牙无敌舰队知乎 编辑:程序博客网 时间:2024/06/05 07:16
一、简述
在使用QGraphicsView过程中,有时候我们需要对view进行缩放,但是对于一般正常的加入view中的item都会随着view的大小变化而变化,但是如果我们想让某些item不随view的缩放进行改变怎么办呢?
很简单,下面讲述两种方法供大家参考学习。
二、代码之路
首先讲述如何通过鼠标滚轮使view放大缩小。很简单,继承QGraphicsView类,然后重写wheelEvent()事件即可。
void MyGraphicsView::wheelEvent(QWheelEvent *event){ // 当前放缩倍数; qreal scaleFactor = this->matrix().m11(); int wheelDeltaValue = event->delta(); // 向上滚动,放大; if (wheelDeltaValue > 0) { this->scale(1.2, 1.2); } // 向下滚动,缩小; else { this->scale(1.0 / 1.2, 1.0 / 1.2); }}
方法一:QGraphicsItem::ItemIgnoresTransformations
QGraphicsItem* item = new QGraphicsItem; item->setFlag(QGraphicsItem::ItemIgnoresTransformations);
Qt助手中setFlag()方法的介绍:
这里我们看一下需要使用到的ItemIgnoresTransformations参数的说明:
这里我们看到,如果给item设置了这个参数,那个这个item就会忽略通过继承从父类得到的transformations,这里的transformations具体包含三个部分rotation、 zoom、shear,这里将会忽略这三个参数的作用。
所以如果你只想忽略某一个,比如只忽略zoom(放大,缩小),其他的想保留,那么就要看一下方法二。
方法二:通过重写QGraphicsItem的paint()方法
其实我们需要知道,item的paint方法什么时候会调用,从哪里调用。我们可以跟踪一下源码,其实第一步是先进入到QGraphicsView的paintEvent事件中,然后在这里创建QPainter对象,并未painter设置当前的transformations(rotation、 zoom、shear),然后将painter对象传给scene对象,通过调用scene的drawItems方法,在drawItems方法中去绘制每一个item(通过调用item的paint方法),这个过程比较复杂,具体大家可以看一下源码。
通过重写QGraphicsItem的paint()方法,实现QGraphicsItem不随QGraphicsView放大缩小而改变大小。同理,这里也可以重新设置rotation或者shear。
void CustomItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget /* = Q_NULLPTR */){ double scaleFactor = 1.0 / painter->matrix().m11(); // view放大或者缩小,我们在paint方法中进行反操作; // 比如view放大了一倍,我们就缩小一倍;view缩小一半,我们就放大一倍; painter->scale(scaleFactor, scaleFactor); __super::paint(painter, option, widget);}
测试代码
void CustomItemTest::initView(){ // 自定义线为红色; // CustomItem中重写了paint方法,所以不会随QGraphicsView放大缩小而改变大小; CustomItem* myItem = new CustomItem; myItem->setLine(QLine(QPoint(200, 200), QPoint(300, 300))); QPen pen; pen.setColor(Qt::red); myItem->setPen(pen); // Qt LineItem 为绿色; QGraphicsLineItem* lineItem = new QGraphicsLineItem; lineItem->setLine(QLine(QPoint(200, 300), QPoint(300, 400))); pen.setColor(Qt::blue); lineItem->setPen(pen); // 方法一 // lineItem->setFlag(QGraphicsItem::ItemIgnoresTransformations); QGraphicsRectItem* rectItem = new QGraphicsRectItem; rectItem->setRect(QRect(QPoint(200, 400), QPoint(300, 500))); CustomView* myView = new CustomView; QGraphicsScene* scene = new QGraphicsScene; scene->addItem(myItem); scene->addItem(lineItem); scene->addItem(rectItem); myView->setScene(scene); QHBoxLayout* myLayout = new QHBoxLayout(this); myLayout->addWidget(myView);}
我们看一下效果,下图中,红色线不会随着随QGraphicsView放大缩小而改变大小,而蓝色的线会随着view放大缩小而改变大小,不仅改变了线的长度还有线的宽度。
然后我们把测试代码中一行注释的代码解开注释,即我们上面讲到的方法一,看一下效果,两条线的宽度和长度都不会改变。
这里我举了线条的例子,像其他Item,比如QGraphicsRectItem、QGraphicsEllipseItem等都可以使用以上两种方法使其不随QGraphicsView放大缩小而改变大小。
但是如果像地图这种对于线条,只想保持线条的宽度不变,这个就必须使用方法二了,这里也需要做一些必要的修改了。
void CustomItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget){ double scaleFactor = painter->matrix().m11(); // QPainter::pen()方法需要注意一下 // 如果之前没有给item设置画笔的话,返回的是一个线宽为0,颜色为黑色,线型为实现的画笔; // 具体看下行Qt助手中的说明; // Returns the item's pen, or a black solid 0-width pen if no pen has been set. // 一般的话如果我们想要给线宽设成某一宽度,并且线宽不随view放大缩小而改变,那就在view放大缩小时重新设置线宽; // 获取到当前的线宽,这里的线宽其实还是之前设置的线宽值; // 比如我们之前设置线宽为 2 ,这里返回的线宽还是 2 ,但是当前的缩放比例变了; // 其实当前的线宽就相当于 penWidth * scaleFactor; // 所以如果我们想要让线宽保持不变,那就需要进行转换,即 penWidth = penWidth / scaleFactor; QPen myPen = this->pen(); // 重新设置画笔线宽; myPen.setWidthF(myPen.widthF() / scaleFactor); painter->setPen(myPen); // 这里就不能用__super::paint(painter, option, widget);方法了; // 因为源码中会重新调用painter->setPen(this->pen());导致线宽设置无效了; painter->drawLine(this->line()); // 如果这里想调用__super::paint(painter, option, widget); // 那就定义一个成员变量m_penWidth来保存初次设置画笔的宽度(写一个set方法); // myPen.setWidthF(m_penWidth / scaleFactor); // this->setPen(pen); // __super::paint(painter, option, widget);}
效果图:
我们看到红线的长度会随着view的缩放而变化,但是线宽却一直保持不变,可以对比下面的矩形,四条边的线宽会不断变化,而蓝色的线只设置了QGraphicsItem::ItemIgnoresTransformations,就一直保持不变。
还有一点需要注意的是,如果给画笔的线宽设置为0(见下方代码),那么在view缩放时,线宽就永远保持为1,不会变化,虽然也达到了一样的效果,但是不能设置线宽为其他值了,比如设置线宽为2、5等等。
QPen myPen = this->pen(); myPen.setWidth(0); painter->setPen(myPen); painter->drawLine(this->line());
代码下载
如何使QGraphicsItem不随QGraphicsView放大缩小而改变大小
(本来上传代码时填写积分为0的,现在没有了这个选项,最低一分,如果没有积分的小伙伴@我)
- 如何使QGraphicsItem不随QGraphicsView放大缩小而改变大小
- 让网页背景图片 固定,不随缩小放大而变化
- 如何让网页背景图片固定不变 不会随着网页的放大缩小而改变
- datatables thead宽度 不会随着table放大缩小而改变
- 如何设定jbutton的大小(使其大小固定,不因布局方式改变而改变???)
- QGraphicsView 如何实现百度地图按照鼠标点进行放大缩小效果
- QGraphicsScene QGraphicsView QGraphicsItem-----
- QGraphicsScene QGraphicsView QGraphicsItem
- QGraphicsView放大和缩小下鼠标位置使用鼠标滚轮
- 当窗口大小改变布局管理器会自动缩小放大控件的大小
- 改变视图的放大 缩小
- 设置背景图片不随浏览器放大而改变(背景固定,只上层div滚动)
- 保持app大小不变 不随系统设置改变而改变
- Android菜鸟练习第十一课 双击放大缩小也可以通过手势改变大小的ZoomImageView
- Qt绘图QGraphicsView、QGraphicsScene、QGraphicsItem
- winform中,如何控制控件位置随窗体的大小改变而改变
- winform中,如何控制控件位置随窗体的大小改变而改变
- 如何实现控件随窗体大小的改变而自动适应其改变
- [题解] HDU 4101 Ali and Baba (BFS)
- JavaScript的数组常用方法
- JAVA封装类和Class类
- Lucene 的核心索引类
- dedecms任意页面调用栏目内容标签{dede:field.content/}的方法
- 如何使QGraphicsItem不随QGraphicsView放大缩小而改变大小
- ZooKeeper 学习 (五) 开源ZkClient操作ZooKeeper
- Android学习笔记(一)
- Android源码学习——linker(2)
- dedecms中无法直接在arctype数据表中直接调取栏目链接
- PAT --- 1002. 写出这个数 (20)
- java关于异常处理只使用try-finally而不使用catch
- Local variables and pointer
- atitit 碎片化学习.docx attilax 总结