自定义的Qt控件特效

实现自定义特效的方法一般是继承QGraphicsEffect类,重写它的draw(...)函数。如果特效需要扩展目标的外矩形则还要重写boundingRectFor(...)函数。使用时用QWidget::setGraphicsEffect(...)函数把特效加到控件上就行了。在不扩展目标外矩形的情况下按照Qt帮助的写法直接绘制就可以,而在需要扩展外矩形的情况则有坑需要注意。这里给出一个需要扩展目标外矩形的例子。实现目标是在控件外部的左上角显示一个绿色的正方形。效果如下:

本文代码在VS2015和Qt5.9下测试通过。下面是头文件:

class MTestEffect : public QGraphicsEffect
{
    Q_OBJECT

public:
    MTestEffect(QObject* parent = 0);

private:
    QRectF boundingRectFor(const QRectF &sourceRect) const override;

    void draw(QPainter *painter) override;
};

CPP文件:

MTestEffect::MTestEffect(QObject* parent) : 
    QGraphicsEffect(parent)
{
}

QRectF MTestEffect::boundingRectFor(const QRectF &sourceRect) const
{
    return sourceRect.adjusted(0, -7, 0, 0);
}

void MTestEffect::draw(QPainter *painter)
{
    QPoint offset;
    QPixmap pixmap = sourcePixmap(Qt::DeviceCoordinates, &offset);
    painter->save();
    painter->setWorldTransform(QTransform());

    painter->fillRect(offset.x(), offset.y(), 6, 6, Qt::green);
    painter->drawPixmap(offset, pixmap);
    painter->restore();
}

这里需要着重看的是draw(...)函数,它取pixmap用的是Qt::DeviceCoordinates而不是Qt::LogicalCoordinates,而且绘制之前要先把worldTransform清空。经过有限的测试在需要扩展目标外矩形的情况下必须这样写,否则绘制效果会出问题。

另外,外扩外矩形只针对子控件,对于顶层窗口是无效的。因为特效不能显示在顶层窗口的外面。

posted @ 2023-08-22 13:38  兜尼完  阅读(53)  评论(0编辑  收藏  举报