Man*_*Way 3 c++ qt qgraphicsview qgraphicsitem qgraphicsscene
该问题与以下问题有关:强制QGraphicsItem保持不变
QGraphicsItem在场景中移动时,我想在一个固定的位置。
建议的解决方案是覆盖void paintEvent(QPaintEvent*)子类的QGraphicsView。
void MyGraphicsView::paintEvent(QPaintEvent*) {
QPointF scenePos = mapToScene(0,0); // map viewport's top-left corner to scene
myItem->setPos(scenePos);
}
Run Code Online (Sandbox Code Playgroud)
但是,问题是我希望场景中的其他所有内容保持不变,即,如果缩放或移动,我希望所有其他内容都QGraphicsItems保持默认状态。
解决此问题的一种较差的方法是void QGraphicsView::paintEvent(QPaintEvent*)从内部调用void 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);
}
Run Code Online (Sandbox Code Playgroud)
但是,这会增加闪烁的行为,my_item因为它首先使用QGraphicsView::paintEvent(event);然后使用添加的代码进行定位
QPointF scenePos = mapToScene(0,0); // map viewport's top-left corner to scene
myItem->setPos(scenePos);
Run Code Online (Sandbox Code Playgroud)
问题是,我是否必须void MyGraphicsView::paintEvent(QPaintEvent*)从头开始重新实现并myItem为所有其他代码的期望行为和默认行为编写代码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>
#include "mygraphicsview.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MyGraphicsView w;
w.show();
return a.exec();
}
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
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());
}
}
Run Code Online (Sandbox Code Playgroud)