图形效果
图形效果是Qt4.6添加的一个新的特色功能,QGraphicsEffect类是所有图形效果的基类。图形效果可以实施在任何一个图形项或者非顶层窗口的任何窗口部件上,只需先创建一个图形效果对象,然后调用setGraphicsEffect()函数来使用这个图形效果即可。Qt提供了4中标准的效果,也可以通过创建QGraphicsEffect的子类来自定义效果。
图形效果类 | 介绍 |
QGraphicsBlurEffect | 提供了一个模糊效果,该效果一般用来减少源对象细节的显示。可使用setBlurRadius( )函数来修改细节等级 默认的模糊半径是5像素;还可以使用setBlurHints( )来指定模糊怎样来执行。 |
QGraphicsColorizeEffect | 该类提供了一个染色效果,该效果用来为源对象进行染色。可用setColor()函数修改颜色 默认是浅蓝色QColor(0,0,192);setStrength()来修改效果的强度(范围0-1.0),默认为1.0 |
QGraphicsDropShadowEffect | 提供了一个阴影效果,可用setColor()来修改阴影颜色,默认是透明的黑灰色,QColor(63,63,63,180) 可使用setOffset()来改变阴影的偏移值,默认为右下方8像素 可使用setBlurRadius()来改变阴影的模糊半径,默认值为1 |
QGraphicsOpacityEffect | 该类提供了一个透明效果,可使源对象透明 可使用setOpacity()函数来修改透明度(0-1.0),0.0表示完全透明,1.0表示完全不透明 |
void MyItem::keyPressEvent(QKeyEvent *event)
{
switch (event->key())
{
case Qt::Key_1 : {
QGraphicsBlurEffect *blurEffect = new QGraphicsBlurEffect;
blurEffect->setBlurHints(QGraphicsBlurEffect::QualityHint); //提高渲染质量
blurEffect->setBlurRadius(8);
setGraphicsEffect(blurEffect);
break;
}
case Qt::Key_2 : {
QGraphicsColorizeEffect *colorizeEffect = new QGraphicsColorizeEffect;
colorizeEffect->setColor(Qt::white);
colorizeEffect->setStrength(0.6);
setGraphicsEffect(colorizeEffect);
break;
}
case Qt::Key_3 : {
QGraphicsDropShadowEffect *dropShadowEffect = new QGraphicsDropShadowEffect;
dropShadowEffect->setColor(QColor(63, 63, 63, 100));
dropShadowEffect->setBlurRadius(2);
dropShadowEffect->setOffset(10);
setGraphicsEffect(dropShadowEffect);
break;
}
case Qt::Key_4 : {
QGraphicsOpacityEffect *opacityEffect = new QGraphicsOpacityEffect;
opacityEffect->setOpacity(0.4);
setGraphicsEffect(opacityEffect);
break;
}
case Qt::Key_5 :
graphicsEffect()->setEnabled(false);
break;
}
}
原本效果:
对前4个item分别设置模糊效果,染色效果,阴影效果,透明效果
动画
使用QGraphicsScene::advance()来推进场景可以很容易实现图形项的动画效果。调用场景的advance()函数就会自动调用场景中所有图形项的advance()函数,而且图形项的advane()函数会被分为两个阶段调用两次。第一次phase为0,告诉所有的图形项场景将要改变;第二次phase为1,在这时才进行具体的操作。
例如我们为自定义图形项添加如下代码:
void MyItem::advance(int phase)
{
// 在第一个阶段不进行处理
if (!phase)
return;
// 图形项向不同方向随机移动
int value = qrand() % 100;
if (value < 25) {
setRotation(45);
moveBy(qrand() % 10, qrand() % 10);
} else if (value < 50) {
setRotation(-45);
moveBy(- qrand() % 10, - qrand() % 10);
} else if (value < 75) {
setRotation(30);
moveBy(- qrand() % 10, qrand() % 10);
} else {
setRotation(-30);
moveBy(qrand() % 10, - qrand() % 10);
}
}
在主函数中添加:
QTimer timer;
QObject::connect(&timer, &QTimer::timeout, &scene, &QGraphicsScene::advance);
timer.start(300);
可产生动画效果。
碰撞检测
图形视图框架提供了图形项之间的碰撞检测,可使用两种方法来实现:
1) 重新实现QGraphicsItem::shape( )函数来返回图形项准确的形状,然后使用默认的collidesWithItem()函数通过两个图形项形状之间的交集来判断是否发生碰撞。如果图形项的形状很复杂,那么进行这个操作是非常耗时的。如果没有重新实现shape()函数,那么它会默认代用boudingRect()函数返回一个简单的矩形。
2) 重新实现collidesWithItem()函数来提供一个自定义的图形项碰撞算法
QGraphicsItem类中的collidesWithItem()函数可判断当前图形项与指定图形项是否碰撞,collidesWithPath()函数可判断当前图形项与指定的路径是否碰撞,collidingItems()函数可返回一个与该图形项碰撞的所有图形项的列表QList<QGraphicsItem *>。
例子如下:
重新实现QGraphicsItem::shape()函数返回图形项准确形状
QPainterPath MyItem::shape()
{
QPainterPath path;
path.addRect(-10, -10, 20, 20);
return path;
}
对paint()进行修改,令图形项与其他图形项碰撞时其轮廓线变为白色。
void MyItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *,
QWidget *)
{
if(hasFocus() || !collidingItems().isEmpty()) {
painter->setPen(QPen(QColor(255, 255, 255, 200)));
} else {
painter->setPen(QPen(QColor(100, 100, 100, 100)));
}
painter->setBrush(brushColor);
painter->drawRect(-10, -10, 20, 20);
}
更多使用可参考Colliding Mice Example示例程序。
图形项组
QGraphicsItemGroup图形项组为图形项提供了一个容器,它可以将多个图形项组合在一起而将它本身以及所有的子图形项看做一个独立的图形项。与父图形项不同,图形项组中的所有图形项都是平等的,例如可以通过拖动其中任意一个来将它们一起进行移动。
MyItem *item1 = new MyItem;
item1->setColor(Qt::blue);
MyItem *item2 = new MyItem;
item2->setColor(Qt::green);
//图形项组
QGraphicsItemGroup *group = new QGraphicsItemGroup;
group->addToGroup(item1);
group->addToGroup(item2);
group->setFlag(QGraphicsItem::ItemIsMovable);
item2->setPos(30, 0);
scene.addItem(group);