我们先暂且不再深究场景和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);
在中间适当的位置加入这句话。在哪里加你们应该能察觉到,实在不行就靠第六感猜。显示效果如下:
现在我想大家已经基本上理解了这是什么意思了。
关于坐标系的内容还剩一小部分,也没有必要因为涉及一些交互,放在这一节也是太长,就下一节讲完吧。