固定QGraphicsItem位置,而不改变其他QGraphicsItems在场景中的行为 [英] Fixed QGraphicsItem position, without changing behaviour of other QGraphicsItems in scene
问题描述
此问题与以下相关:强制QGraphicsItem保持搁置
我想在场景中移动时在固定位置上有 QGraphicsItem
。
建议的解决方案是覆盖子类别<$ c $的 void paintEvent(QPaintEvent *)
c> QGraphicsView 。
void MyGraphicsView :: paintEvent(QPaintEvent *){
QPointF scenePos = mapToScene(0,0); //将viewport的左上角映射到场景
myItem-> setPos(scenePos);
}
但是,问题是我想让场景中的其他东西保持原样,即如果我缩放或移动我想要所有其他 QGraphicsItems
作为默认行为。
一个很差的解决方法这是调用 void MyGraphicsView :: paintEvent(QPaintEvent *)
void QGraphicsView :: paintEvent(QPaintEvent *)
。
void MyGraphicsView :: paintEvent(QPaintEvent * event){
,还是有更简单的方法来做到这一点?
QGraphicsView :: paintEvent(event);
QPointF scenePos = mapToScene(0,0); //将viewport的左上角映射到场景
myItem-> setPos(scenePos);但是,这会给my_item 添加一个闪烁的行为,因为<$ c $ b> / code>,因为它首先使用
的所有行为以及所有其他QGraphicsView :: paintEvent(event);
定位,然后使用添加的代码QPointF scenePos = mapToScene(0,0); //将viewport的左上角映射到场景
myItem-> setPos(scenePos);问题是,我是否必须重新实现void MyGraphicsView :: a:
$ b paint< code> myItem的默认行为,从头开始绘制paintEvent(QPaintEvent *)
QGraphicsItems
谢谢。
解决方案我认为这是您要寻找的:
http://qt-project.org/doc/qt-4.8/qgraphicsitem .html#setFlag
QGraphicsItem :: ItemIgnoresTransformations
从文档中的描述:
项目忽略继承的转换(即,它的位置仍然锚定到其父,父或视图旋转,缩放或剪切变换被忽略)。此标志对于将文本标签项保持水平和不缩放非常有用,因此如果视图被转换,它们仍然可以被读取。设置时,项目的视图几何和场景几何将单独维护。您必须调用deviceTransform()来映射坐标并检测视图中的冲突。默认情况下,禁用此标志。这个标志是在Qt 4.3中引入的。注意:设置此标志后,您仍然可以对项目本身进行缩放,而且缩放转换将影响项目的子项。
想要父母一切都做到其他东西。然后,您移动或缩放或旋转单个图形组以影响除了不可变换对象之外的所有内容。
https://qt-project.org/doc/qt-4.8/graphicsview.html# the-graphics-view-coordinate-system
https://qt-project.org/doc/qt-4.8/painting-transformations.html (一个很酷的例子,虽然它没有显示这个功能真的)
http ://qt-project.org/doc/qt-4.8/demos-chip.html (使用
QGraphicsView
的大例子)
希望有帮助。
编辑:
使用父级实现静态图层:
main.cpp
include< QApplication>
#includemygraphicsview.h
int main(int argc,char * argv [])
{
QApplication a(argc,argv);
MyGraphicsView w;
w.show();
return a.exec();
}
mygraphicsview.h
#ifndef MYGRAPHICSVIEW_H
#define MYGRAPHICSVIEW_H
#include< QGraphicsView>
#include< QGraphicsItemGroup>
#include< QMouseEvent>
类MyGraphicsView:public QGraphicsView
{
Q_OBJECT
public:
MyGraphicsView(QWidget * parent = 0);
〜MyGraphicsView();
public slots:
void mousePressEvent(QMouseEvent * event);
void mouseReleaseEvent(QMouseEvent * event);
void mouseMoveEvent(QMouseEvent * event);
private:
bool down;
QPointF m_last_pos;
QGraphicsItemGroup * m_group;
};
#endif // MYGRAPHICSVIEW_H
mygraphicsview.cpp
#includemygraphicsview.h
#include< QGraphicsItem>
#include< QGraphicsEllipseItem>
#include< QGraphicsTextItem>
MyGraphicsView :: MyGraphicsView(QWidget * parent)
:QGraphicsView(parent)
{
down = false;
this-> setScene(new QGraphicsScene);
//没有添加到组中的任何东西将保持为
this-> scene() - > addEllipse(20,20,50,50);
this-> scene() - > addEllipse(180,180,50,50);
this-> scene() - > addText(用鼠标点击并拖动,只移动小点。
//这个组将接收所有的转换
m_group = new QGraphicsItemGroup;
for(int r = 0; r <20; r ++)
{
for(int c = 0; c <20; c ++)
{
if(c%5 == 0& r%5 == 0)
{
QGraphicsTextItem * txt = new QGraphicsTextItem(QString :: number(r)+,+ QString :: number(c));
m_group-> addToGroup(txt);
txt-> setPos(r * 100,c * 100);
}
m_group-> addToGroup(new QGraphicsEllipseItem(r * 100,c * 100,5,5));
}
}
this-> scene() - > addItem(m_group);
}
MyGraphicsView ::〜MyGraphicsView()
{
}
void MyGraphicsView :: mousePressEvent(QMouseEvent * event)
{
m_last_pos = mapToScene(event-> pos());
down = true;
}
void MyGraphicsView :: mouseReleaseEvent(QMouseEvent *)
{
down = false;
}
void MyGraphicsView :: mouseMoveEvent(QMouseEvent * event)
{
if(down)
{
QPointF temp = mapToScene event-> pos());
QPointF delta = temp - m_last_pos;
m_last_pos = temp;
//将转换应用到组,而不是场景!
m_group-> translate(delta.x(),delta.y());
}
}
This question is related to: Forcing QGraphicsItem To Stay Put
I'd like to have a
QGraphicsItem
on a fixed location when moving around in the scene.The suggested solution is to override the
void paintEvent(QPaintEvent*)
of the sub-classedQGraphicsView
.void MyGraphicsView::paintEvent(QPaintEvent*) { QPointF scenePos = mapToScene(0,0); // map viewport's top-left corner to scene myItem->setPos(scenePos); }
However, the problem is that I want everything else in the scene to stay intact, i.e. if I zoom or move I want all other
QGraphicsItems
to behave as default.One poor way of solving this is to call
void QGraphicsView::paintEvent(QPaintEvent*)
from withinvoid MyGraphicsView::paintEvent(QPaintEvent*)
.void MyGraphicsView::paintEvent(QPaintEvent* event) { QGraphicsView::paintEvent(event); QPointF scenePos = mapToScene(0,0); // map viewport's top-left corner to scene myItem->setPos(scenePos); }
However, this adds a flickering behaviour to
my_item
since it's positioned first usingQGraphicsView::paintEvent(event);
and then using the added codeQPointF scenePos = mapToScene(0,0); // map viewport's top-left corner to scene myItem->setPos(scenePos);
The question is, do I have to re-implement
void MyGraphicsView::paintEvent(QPaintEvent*)
from scratch and write code for both the desired behaviour ofmyItem
and the default behaviour of all otherQGraphicsItems
, or is there an easier way to do this?Thank you.
解决方案I think this is what you are looking for:
http://qt-project.org/doc/qt-4.8/qgraphicsitem.html#setFlag
QGraphicsItem::ItemIgnoresTransformations
Description from the docs:
The item ignores inherited transformations (i.e., its position is still anchored to its parent, but the parent or view rotation, zoom or shear transformations are ignored). This flag is useful for keeping text label items horizontal and unscaled, so they will still be readable if the view is transformed. When set, the item's view geometry and scene geometry will be maintained separately. You must call deviceTransform() to map coordinates and detect collisions in the view. By default, this flag is disabled. This flag was introduced in Qt 4.3. Note: With this flag set you can still scale the item itself, and that scale transformation will influence the item's children.
You may also want to parent everything that does pan around to something else. Then, you move or scale or rotate a single graphics group to affect everything except your "un-transformable" objects.
https://qt-project.org/doc/qt-4.8/graphicsview.html#the-graphics-view-coordinate-system
https://qt-project.org/doc/qt-4.8/painting-transformations.html (a cool example, though it doesn't show this feature really)
http://qt-project.org/doc/qt-4.8/demos-chip.html (great example of using
QGraphicsView
)Hope that helps.
EDIT:
Example showing how you can achieve a static layer using parenting:
main.cpp
#include <QApplication> #include "mygraphicsview.h" int main(int argc, char *argv[]) { QApplication a(argc, argv); MyGraphicsView w; w.show(); return a.exec(); }
mygraphicsview.h
#ifndef MYGRAPHICSVIEW_H #define MYGRAPHICSVIEW_H #include <QGraphicsView> #include <QGraphicsItemGroup> #include <QMouseEvent> class MyGraphicsView : public QGraphicsView { Q_OBJECT public: MyGraphicsView(QWidget *parent = 0); ~MyGraphicsView(); public slots: void mousePressEvent(QMouseEvent *event); void mouseReleaseEvent(QMouseEvent *event); void mouseMoveEvent(QMouseEvent *event); private: bool down; QPointF m_last_pos; QGraphicsItemGroup * m_group; }; #endif // MYGRAPHICSVIEW_H
mygraphicsview.cpp
#include "mygraphicsview.h" #include <QGraphicsItem> #include <QGraphicsEllipseItem> #include <QGraphicsTextItem> MyGraphicsView::MyGraphicsView(QWidget *parent) : QGraphicsView(parent) { down = false; this->setScene(new QGraphicsScene); // Anything not added to the "group" will stay put this->scene()->addEllipse(20, 20, 50, 50); this->scene()->addEllipse(180, 180, 50, 50); this->scene()->addText("Click and drag with the mouse to move only the tiny dots."); // This group will receive all transformations m_group = new QGraphicsItemGroup; for(int r = 0; r < 20; r ++) { for(int c = 0; c < 20; c++) { if(c % 5 == 0 && r % 5 == 0) { QGraphicsTextItem * txt = new QGraphicsTextItem(QString::number(r) + "," + QString::number(c)); m_group->addToGroup(txt); txt->setPos(r*100, c*100); } m_group->addToGroup(new QGraphicsEllipseItem(r *100, c*100, 5, 5)); } } this->scene()->addItem(m_group); } MyGraphicsView::~MyGraphicsView() { } void MyGraphicsView::mousePressEvent(QMouseEvent *event) { m_last_pos = mapToScene(event->pos()); down = true; } void MyGraphicsView::mouseReleaseEvent(QMouseEvent *) { down = false; } void MyGraphicsView::mouseMoveEvent(QMouseEvent *event) { if(down) { QPointF temp = mapToScene(event->pos()); QPointF delta = temp - m_last_pos; m_last_pos = temp; // Apply transformation to the group, not the scene! m_group->translate(delta.x(), delta.y()); } }
这篇关于固定QGraphicsItem位置,而不改变其他QGraphicsItems在场景中的行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!