我们先暂且不再深究场景和view的坐标系,先研究一下如何定义一个自己的图形项,首先定义一个Qt类:
#ifndef MYGraphicsITEM_H #define MYGraphicsITEM_H #include <QGraphicsItem> class MyGraphicsItem : public QGraphicsItem { public: MyGraphicsItem(QGraphicsItem * parent = Q_NULLPTR); ~MyGraphicsItem(); QRectF boundingRect() const; void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); }; #endif一定要注意这里面千万不能加Q_OBJECT宏,因为这个继承自QGraphicsItem,并不属于QObject类的子类,如果加上编译的时候会报错。
注意除了构造和析构以外,里面还有两个函数,这都是虚继承的父类的函数,只有实现了这两个函数,才能使用这个类。
第一个函数是用来指定自己的图形项的矩形边界的。我们知道图形项都要有自己的边界,这样才能检测场景中某个点属于哪个图形项。第二个函数是用来画图形项里面的内容的。一定要注意,我们的画笔是有粗细的,所以需要附加一个边界量,保证画笔不会画到图形项外面。画到图形项外面的不会被显示出来。
#include "mygraphicsitem.hpp" #include <QPainter> MyGraphicsItem::MyGraphicsItem(QGraphicsItem * parent):QGraphicsItem(parent) { } MyGraphicsItem::~MyGraphicsItem() { } QRectF MyGraphicsItem::boundingRect() const { qreal penWidth = 1; return QRectF(0 - penWidth / 2, 0 - penWidth / 2, 20 + penWidth, 20 + penWidth); } void MyGraphicsItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) { painter->setBrush(Qt::red); painter->drawRect(5, 5, 15, 15); }程序如上,我们可以看到矩形的边界多了一个笔粗的一半,因为笔画的线会一半在左边一半在右边(线是有粗细的)。以及下面的函数,这里我们画线并没有画在边界上,所以其实上面的函数也不用预留笔粗的空间。但是如果画线painter->drawRect(0, 0, 20, 20); 则预留的笔粗空间就是必须的了。
注意在每个图形项中,它的坐标原点是属于它自己的,你把它画在场景中的位置,是它自己的坐标原点的位置,这句话现在不理解也没关系,下面看程序:
//用来实验GraphicsItem的程序 // 新建场景 QGraphicsScene *scene = new QGraphicsScene; // 创建矩形图形项 MyGraphicsItem *item = new MyGraphicsItem; // 将图形项添加到场景中 scene->addItem(item); // 为场景创建视图 QGraphicsView *view = new QGraphicsView(scene); scene->setForegroundBrush(QColor(255, 255, 0, 100)); scene->setBackgroundBrush(QPixmap("./ShowDebug/wed.png")); view->resize(400, 300); view->show(); QGraphicsView *view2 = new QGraphicsView(scene); view2->resize(400, 300); view2->show();我们看到addItem,这里并没有指定默认的item位置,所以说item的原点就设置在了scene的原点:
注意这里的橘色小方块在图形项的左上角是(5,5)点,在图片的场景中的位置也是(5,5)点,这说明场景的原点和图形项的原点默认的话是重合的。
现在我们这么设置:
item->setPos(40, 40);在中间适当的位置加入这句话。在哪里加你们应该能察觉到,实在不行就靠第六感猜。显示效果如下:
现在我想大家已经基本上理解了这是什么意思了。
关于坐标系的内容还剩一小部分,也没有必要因为涉及一些交互,放在这一节也是太长,就下一节讲完吧。
