一、简述
- 图形视图框架提供了一个基于图形项的模型视图编程方法
- 组成三元素:场景(QGraphicsScene类)、视图(QGraphicsView类)、图形项(QGraphicsItem类)。
- 多个视图可以看到同一个场景,场景包含各种各样的几何形状的图形项(图形项的行为:如移动、叠加、碰撞、拖动、缩放、旋转等)。
- QGraphicScene(场景)可以管理多个图形项QGraphicsItem(如:QGraphicsRectItem(矩形的图形项,即图元)),QGraphicsView(视图)关联场景可以让场景中的所有图形项可视化。
二、简单应用——发射爱心碰撞
在视图类中新建一个场景,以及相应的图元(小人物、爱心),将图元添加到场景中,将视图与场景关联,最后显示视图。场景是管理图元的,所有的图元必须添加到一个场景中,但是场景本身无法可视化,要看到场景上的内容,必须用上视图。
1、实现效果
2、源码:
2.1图元类:
class MyItem : public QObject,public QGraphicsItem//要加QObject
{
Q_OBJECT
public:
int type;
bool isLife;
QString fileName;
QPixmap pix;
//方法
MyItem();
MyItem(QString fileName,int type,bool isLife);
QRectF boundingRect() const override;//boundingRect虚函数
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = nullptr) override;
public slots:
void advance(int phase) override;
signals:
void itemCollding();//用来发送信号,不要定义方法
};
MyItem::MyItem(QString fileName, int type, bool isLife)//fileName加载图片
{
pix.load(fileName);//pix存图片
this->type = type;
this->isLife = isLife;
}
//画边界
QRectF MyItem::boundingRect() const
{
qreal penWidth = 1;
return QRectF(0,0,pix.width(),pix.height());
}
//重绘
void MyItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
//标明该参数没有使用
Q_UNUSED(option)
Q_UNUSED(widget)
painter->drawPixmap(0,0,pix.width(),pix.height(),pix);//不是pix.width()图片拖尾
}
//移动,用定时器,绑定advance
void MyItem::advance(int phase)
{
qDebug()<<"advance";
if(collidingItems().isEmpty())
{
if(this->type == 1)//左边爱心的发射
{
moveBy(20,0);
}
if(this->type == 2)
{
moveBy(-20,0);
}
}
else
{
this->isLife = true;//要给为true,不然碰撞后弹不出界面
emit itemCollding();//发送信号给视图类
}
}
2.2视图类:
class animationView : public QGraphicsView
{
Q_OBJECT
public:
animationView();
QGraphicsScene *pscene ;//场景指针
MyItem *item1;//图元
MyItem *item2;
MyItem *item4;
MyItem *item3;
MyItem *item5;
MyItem *item6;
QTimer *time1;//定时器
QTimer *time2;
public slots:
void itemMoveStopSlot();//要使用Q_OBJECT
};
animationView::animationView()
{
this->resize(900,800);
/*1、创建场景、图元*/
pscene = new QGraphicsScene;
item1 = new MyItem(":/love-l.png",1,false);//左边爱心
item2 = new MyItem(":/love-r.png",2,false);
item5 = new MyItem(":/l1.png",5,false);//左边小人物
item6 = new MyItem(":/r1.png",6,false);
/*2、位置及数量关系*/
item5->setPos(0,230);
item6->setPos(680,230);
item1->setPos(100,this->height()/3);
item2->setPos(600,this->height()/3);
pscene->addItem(item1);
pscene->addItem(item2);
pscene->addItem(item5);
pscene->addItem(item6);
this->setScene(pscene);
/*3、移动——定时器*/
time1 = new QTimer;
connect(time1, SIGNAL(timeout()), pscene,SLOT(advance()));
time1->start(1000);
/*4、item1发送信号,不用两个定时器*/
connect(item1, SIGNAL(itemCollding()), this,SLOT(itemMoveStopSlot()));
}
void animationView::itemMoveStopSlot()
{
/*方法一:用connect(item1, SIGNAL(itemCollding()), this,SLOT(itemMoveStopSlot()));*/
time1->stop();
delete this->item1;
delete this->item2;
item3 = new MyItem(":/love.png",3,false);
pscene->addItem(item3);//中间显示出玫瑰花
item3->setPos(180,120);
}
附方法二:利用两个定时器
注:实现过程可能出现bug:
解决步骤:
- 重新写图元类class(继承QObject、QGraphicsItem,包含Q_OBJECT宏)
- 构建中点击qmake
- 重新构建