编程工具为vs2010+qt 5.1.2
由于第一次刚使用qt,所以就写写博客分享一个qt新手从入门到放弃这个过程。
这个小设计使用QT中的QGraphics框架,这个框架适用于2D图像和动画的操作,包括各种变换以及检测等,而在其中的Colliding函数对于碰撞检测这一功能的实现非常简单。
QRectF boundingRect() const;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
QWidget *widget);
QPainterPath shape() const;
void setSpeed(qreal i,qreal j); //速度
void advance(int phase);
私有成员有X,Y方向上的运动速度。
这里采用QDialog对话框获取速度,再通过函数setSpeed设置物体的速度。
QString Xspeed = QInputDialog::getText(NULL, " item Xspeed",
"Please input your item XSpeed",
QLineEdit::Normal,
"Xspeed Input",
&isOK);
QString Yspeed = QInputDialog::getText(NULL, " item Yspeed",
"Please input your item YSpeed",
QLineEdit::Normal,
"Yspeed Input",
&isOK);
qreal xspeed = Xspeed.toDouble( );
qreal yspeed = Yspeed.toDouble( );
setSpeed( xspeed , yspeed );
painter->drawEllipse(pos().x(),pos().y(),radius*2,radius*2);
boundingRect函数是返回包含Item的最小矩形,一般用于绘图和碰撞检测。而shape函数与boundingrect函数类似,但是shape更为精确,因为shape返回的是PainterPath而boundingRect返回的是一个矩形。
QRectF MyItem::boundingRect() const
{
qreal penWidth = 1;
return QRectF(pos().x() - penWidth / 2, pos().y() - penWidth / 2,
radius*2 + penWidth, radius*2 + penWidth);
}
QPainterPath MyItem::shape() const
{
QPainterPath path;
path.addEllipse( pos().x() , pos().y() , radius*2 , radius*2 ); //图形项的真实大小
return path;
}
运动函数利用advance和计时器就可以实现,反弹就要使用colliding函数和坐标计算判断。
void MyItem::advance( int phase )
{
if(!phase) return; //如果phase为0,则结束
qreal x=this->pos().x();//更新位置
qreal y=this->pos().y();
if(y<=0||y+radius>=SceneHeight/2)//碰撞Y方向的墙
{
yspeed*=-1;
}
else if(x<=0||x+radius>=SceneWidth/2) //碰撞X方向的墙
{
xspeed*=-1;
}
if(!collidingItems().isEmpty()) //碰撞检测
{
xspeed*=-1;
yspeed*=-1;
}
moveBy( xspeed , yspeed );
}
遗憾没有实现边界和视图窗口的自适应,就是拉大视图,小球的运动边界也改变。
不知道怎么实现这个功能~
2019.11.7:
可以通过重写ResizeEvent事件来实现上述窗口的自适应功能。
ps:
QGraphicsView::ResizeEvent函数已实现,需要继承GraphicsView来重写resizeEvent函数。
void QGraphicsView::resizeEvent(QResizeEvent *event)
{
SceneHeight=this->height();
SceneWidth =this->width();
}
参考文档