QStyleOptionGraphicsItem实现自绘按钮悬浮按下状态

Qt官方自带的例子animatedtiles,该工程存放在Qt安装目录下的

Examples\Qt-XX.XX.XX\widgets\animation\animatedtiles 目录

其中XX.XX.XX为Qt的版本号,如:5.14.1。有如下代码:

class Button : public QGraphicsWidget
{
    Q_OBJECT
public:
    ......   // 该部分代码略,请参见Qt官方自带的例子查看

    void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *) override
    {
        bool down = option->state & QStyle::State_Sunken;
        QRectF r = boundingRect();
        QLinearGradient grad(r.topLeft(), r.bottomRight());
        grad.setColorAt(down ? 1 : 0, option->state & QStyle::State_MouseOver ? Qt::white : Qt::lightGray);
        grad.setColorAt(down ? 0 : 1, Qt::darkGray);
        painter->setPen(Qt::darkGray);
        painter->setBrush(grad);
        painter->drawEllipse(r);
        QLinearGradient grad2(r.topLeft(), r.bottomRight());
        grad.setColorAt(down ? 1 : 0, Qt::darkGray);
        grad.setColorAt(down ? 0 : 1, Qt::lightGray);
        painter->setPen(Qt::NoPen);
        painter->setBrush(grad);
        if (down)
            painter->translate(2, 2);
        painter->drawEllipse(r.adjusted(5, 5, -5, -5));
        painter->drawPixmap(-_pix.width()/2, -_pix.height()/2, _pix);
    }

      ...... // 该部分代码略,请参见Qt官方自带的例子查看
};

第9行代码:判断按钮是否被鼠标按下了,如果按钮被按下,则:

ption->state & QStyle::State_Sunken即down就为true,否则就会false。

第10-16行:创建一个渐变画刷和一个Qt::darkGray颜色的画笔。并利用该画刷、画笔在按钮所在最小外包围矩形中绘制了一个圆形。创建画刷的思路是:

  • 从按钮最小外包围矩形左上角到右下角进行渐变。
  • 如果鼠标将按钮按下 了,则设置渐变的起点颜色为Qt::darkGray、终点颜色为Qt::white。

        此时第12、13行代码变为:

grad.setColorAt(1, Qt::white);
grad.setColorAt(0, Qt::darkGray);

 

此时绘制出的按钮如下(注意:17行后的代码都注释掉了,这里仅仅显示的是17行之前的代码效果):

 可以看到从左上角的深灰渐变到右下角的白色。

  • 如果鼠标没将按钮按下,仅仅是悬浮在按钮上面,则此时第12、13行代码变为:
grad.setColorAt(0, Qt::white);
grad.setColorAt(1, Qt::darkGray);

 

此时绘制出来的效果如下(注意:17行后的代码都注释掉了,这里仅仅显示的是17行之前的代码效果):

 可以看到从左上角的白色渐变到右下角的深灰色。

  • 如果鼠标既没按下按钮也没悬浮在按钮上面,则第12、13行代码如下:
grad.setColorAt(0, Qt::lightGray);
grad.setColorAt(1, Qt::darkGray);
 

效果如下(注意:17行后的代码都注释掉了,这里仅仅显示的是17行之前的代码效果):

 

 可以看到从左上角的浅灰色渐变到右下角的深灰色。

第17-21行:如果鼠标被按下,则创建浅灰到深灰渐变画刷;如果鼠标没按下按钮,则创建深灰到浅灰渐变画刷。注:第20行画笔一定要是Qt::NoPen,否则第24行创建的圆形和第16行创建的圆形有画笔留下的痕迹,进而明显可以看出不是一个整体的圆形。

第24行:因为15行设置的渐变画刷和21行设置的渐变画刷不一样,再加上本行将按钮最小外包矩形宽高缩小10个单位,这样创建的两个圆形有显著的凸凹视觉效果,更逼真,如下(注释掉了第25行代码后的效果):

第22-23行:如果按钮被按下了,就将坐标系向右、向下平移2个单位,这样就会给人造成按下的逼真视觉效果。 

至此,本函数分析完毕!

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
如果你想要设置一个按钮悬浮状态,可以使用OwnerDraw属性,并重载WM_DRAWITEM消息来自定义按钮的绘制。 下面是一个简单的示例代码: 首先在资源文件中将按钮Style属性设置为OwnerDraw,然后在窗口类的消息处理函数中添加下面的代码: ```c++ case WM_DRAWITEM: { LPDRAWITEMSTRUCT lpdis = (LPDRAWITEMSTRUCT)lParam; if (lpdis->hwndItem == hButton) // hButton是按钮的句柄 { // 绘制按钮的背景 if (lpdis->itemState & ODS_SELECTED) SetBkColor(lpdis->hDC, RGB(255, 0, 0)); // 设置选中状态的背景颜色为红色 else if (lpdis->itemState & ODS_FOCUS) SetBkColor(lpdis->hDC, RGB(0, 255, 0)); // 设置获取焦点状态的背景颜色为绿色 else SetBkColor(lpdis->hDC, RGB(0, 0, 255)); // 设置普通状态的背景颜色为蓝色 ExtTextOut(lpdis->hDC, lpdis->rcItem.left, lpdis->rcItem.top, ETO_OPAQUE, &lpdis->rcItem, NULL, 0, NULL); // 填充背景 // 绘制按钮的文本 TCHAR szText[256]; GetWindowText(lpdis->hwndItem, szText, 256); SetTextColor(lpdis->hDC, RGB(255, 255, 255)); // 设置文本颜色为白色 DrawText(lpdis->hDC, szText, -1, &lpdis->rcItem, DT_CENTER | DT_VCENTER | DT_SINGLELINE); // 居中绘制文本 } break; } ``` 在上面的代码中,我们首先判断当前消息所涉及的按钮是否是我们要处理的按钮,然后根据按钮状态设置对应的背景颜色,最后填充背景并绘制文本。 需要注意的是,这只是一个简单的示例代码,实际使用时可能需要根据具体情况进行调整。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值