C++ 固定QGraphicsItem位置,而不更改场景中其他QGraphicsItem的行为

C++ 固定QGraphicsItem位置,而不更改场景中其他QGraphicsItem的行为,c++,qt,qgraphicsview,qgraphicsitem,qgraphicsscene,C++,Qt,Qgraphicsview,Qgraphicsitem,Qgraphicsscene,这个问题涉及: 在场景中移动时,我希望在固定位置上放置一个QGraphicsItem 建议的解决方案是覆盖子类QGraphicsView的void paintEvent(QPaintEvent*) void MyGraphicsView::paintEvent(QPaintEvent*) { QPointF scenePos = mapToScene(0,0); // map viewport's top-left corner to scene myItem->setPos(sc

这个问题涉及:

在场景中移动时,我希望在固定位置上放置一个
QGraphicsItem

建议的解决方案是覆盖子类
QGraphicsView
void paintEvent(QPaintEvent*)

void MyGraphicsView::paintEvent(QPaintEvent*) {
  QPointF scenePos = mapToScene(0,0); // map viewport's top-left corner to scene
  myItem->setPos(scenePos);
}
但是,问题是我希望场景中的所有其他内容保持不变,也就是说,如果我缩放或移动,我希望所有其他
QGraphicsItems
作为默认值

解决此问题的一个糟糕方法是从
void MyGraphicsView::paintEvent(QPaintEvent*)调用
void QGraphicsView::paintEvent(QPaintEvent*)

但是,这会给
my_项添加闪烁行为,因为它首先使用
QGraphicsView::paintEvent(事件)定位
然后使用添加的代码

QPointF scenePos = mapToScene(0,0); // map viewport's top-left corner to scene
myItem->setPos(scenePos);
问题是,我是否必须从头开始重新实现
void MyGraphicsView::paintEvent(QPaintEvent*)
,并为
myItem
的所需行为和所有其他
QGraphicsItems
的默认行为编写代码,或者是否有更简单的方法来做到这一点


多谢各位

我想这就是你想要的:

QGraphicsItem::ItemIgnoresTransformations

文档中的描述:

该项忽略继承的变换(即,其位置仍定位到其父项,但忽略父项或视图旋转、缩放或剪切变换)。此标志对于保持文本标签项水平且不缩放非常有用,因此,如果视图被转换,它们仍然是可读的。设置后,将分别维护项目的视图几何体和场景几何体。必须调用deviceTransform()来映射视图中的坐标并检测碰撞。默认情况下,此标志处于禁用状态。Qt4.3中引入了此标志。注意:设置此标志后,您仍然可以缩放项目本身,并且缩放变换将影响项目的子项

您可能还希望将所有平移到其他对象的对象作为父对象。然后,移动、缩放或旋转单个图形组,以影响除“不可转换”对象之外的所有对象

(这是一个很酷的例子,虽然它没有真正显示此功能)

(使用
QGraphicsView
的好例子)

希望有帮助

编辑:

显示如何使用父项实现静态层的示例:

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”
int main(int argc,char*argv[])
{
质量保证申请a(argc、argv);
MyGraphicsView;
w、 show();
返回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
\ifndef MYGRAPHICSVIEW\u H
#定义我的图形视图
#包括
#包括
#包括
类MyGraphicsView:公共QGraphicsView
{
Q_对象
公众:
MyGraphicsView(QWidget*parent=0);
~MyGraphicsView();
公众时段:
作废鼠标压力事件(QMouseEvent*事件);
无效mouseReleaseEvent(QMouseEvent*事件);
作废mouseMoveEvent(QMouseEvent*事件);
私人:
下钻;
QPointF m_last_pos;
QGraphicsSiteMgroup*m_组;
};
#endif//MYGRAPHICSVIEW\u 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());
    }
}
#包括“mygraphicsview.h”
#包括
#包括
#包括
MyGraphicsView::MyGraphicsView(QWidget*父项)
:QGraphicsView(父级)
{
向下=假;
此->设置场景(新的QGraphicscene);
//没有添加到“组”中的任何内容都将保持不变
这个->场景()->addEllipse(20,20,50,50);
这个->场景()->addEllipse(180,180,50,50);
此->场景()->添加文本(“单击并用鼠标拖动以仅移动小点”);
//此组将接收所有转换
m_组=新的QGraphicsSiteMgroup;
对于(int r=0;r<20;r++)
{
对于(int c=0;c<20;c++)
{
如果(c%5==0&&r%5==0)
{
QGraphicsTextItem*txt=新的QGraphicsTextItem(QString::number(r)+“,“+QString::number(c));
m_组->添加组(txt);
txt->setPos(r*100,c*100);
}
m_group->addToGroup(新的QGraphicsSellipseitem(r*100,c*100,5,5));
}
}
此->场景()->附加项(m_组);
}
MyGraphicsView::~MyGraphicsView()
{
}
void MyGraphicsView::MousePresseEvent(QMouseEvent*事件)
{
m_last_pos=maptosene(事件->pos());
向下=真;
}
void MyGraphicsView::mouseReleaseEvent(QMouseEvent*)
{
向下=假;
}
void MyGraphicsView::mouseMoveEvent(QMouseEvent*事件)
{
如果(向下)
{
QPointF temp=maptosene(事件->位置());
QPointF delta=温度-最后一个位置;
m_last_pos=温度;
//将变换应用于组,而不是场景!
m_group->translate(delta.x(),delta.y());
}
}

为什么不在调用
setPos()
之后调用
paintEvent()
?@Chris它会产生更糟糕的效果。在整个屏幕上显示项目的痕迹。您能使用该功能并查看是否收到一些通知吗?也许
QGraphicsItem::itemscenepositionhasschanged
就是您需要的。您必须启用
QGraphicsItem::itemssendscenepositionchanges
标志才能使其工作。另请参见抱歉,itemsignoretransformations已设置。这无助于避免在场景中移动。您是否尝试将其他所有内容作为另一个
QGraphicsSiteMgroup
的子对象,然后将翻译应用于该组而不是场景?这仍然需要让我从头开始实现
void MyGraphicsView::paintEvent(QPaintEvent*)
,对吗?我会在接下来的几分钟里举一个例子。如果你做对了父母,你就不需要这样做。
#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());
    }
}