• Qt之实现360安全卫士主界面(三)


          这篇博文主要讲述360安全卫士工具栏的创建;工具栏由图片和文字组成,当鼠标移到工具栏按钮上时,需要有些特征表达该现象,如背景色变化等;当然鼠标单击工具栏按钮时,同样也要有些特征,并且这个特征区别于鼠标移到按钮上的特征;写起来有些拗口,我给大家先看看我实现的效果图。

          单击按钮时和鼠标移到按钮上时,按钮背景会不同,并且单击其他按钮时,已单击的那个按钮背景应该恢复。下面讲解其具体实现。

    一、工具栏的创建

          工具栏当然是自定义的部件了(继承于QWidget),工具栏上的那些按钮都是继承于QToolButton;其中有9个按钮,最右边的是label;工具栏类的成员变量如下所示:

    View Code
    QList<MyBtn*> m_listMyBtnPoint;//自定义按钮
    QList<QString> m_listMyStr;//按钮对应的文本
    QLabel *m_pLabel;//label,显示logo

          首先当然是创建这些子部件了,和一般的没啥区别:

    View Code
    //CreateWidget创建部件
    void ToolBar::CreateWidget()
    {
    //文本例子
    m_listMyStr<<"Examine"<<"KillTrojan"<<"CleanDust"<<"LeakRepair"<<"SysRepair"
    <<"CleanCom"<<"FunFull"<<"SoftMan"<<"OptSpeed";
    //创建toolbutton
    for(int nIndex = 0;nIndex<WIDGET_CNT;++nIndex)
    {
    //图像资源路径
    QString strImage = QString(":/image/%1.png").arg(nIndex+1);
    //创建自定义QToolButton(MyBtn)
    m_listMyBtnPoint.append(new MyBtn(strImage,m_listMyStr[nIndex],this));
    //设置toolbutton的位置
    m_listMyBtnPoint.at(nIndex)->move(nIndex*TOOLWIDGET_H+VALUE_DIS,0);
    //该信号槽设置其他按钮的按下状态bool值
    connect(m_listMyBtnPoint.at(nIndex),SIGNAL(signal_parent(void*)),this,SLOT(slot_set(void*)));
    }
    //创建label
    m_pLabel = new QLabel(this);
    m_pLabel->setPixmap(QPixmap(":/image/logo.png"));
    }

          工具栏里的按钮和label都是手动定位(即设置位置信息),所以重写了resizeEvent事件,在resizeEvent事件里进行部件定位,如下所示:

    View Code
    //resizeEvent
    void ToolBar::resizeEvent (QResizeEvent * event)
    {
    //按钮垂直居中
    m_pLabel->move(rect().width()-m_pLabel->pixmap()->width()-VALUE_DIS,(rect().height()-m_pLabel->pixmap()->height())/2);
    }

          大家可能会想:在resizeEvent事件里只对label进行定位了,那其他9个按钮了?因为其他9个按钮都是从最左边(也就是0)计算相对位移,而label是从最右边计算的,通过rect()函数获得工具栏的最右边位置信息;按钮在创建部件函数的时候就定位了位置,如果label也在那个时候定位位置的话是错误的,因为那是工具栏部件的大小是未知的,所以rect()函数返回的值也是未知的;当放在resizeEvent事件中进行处理时,工具栏部件显示出来的时候,其大小都是可以确定的。

    二、工具栏按钮效果设置

          工具栏按钮继承于QToolButton;首先是设置按钮的基本显示效果了,去掉Qt自带的效果;包括文本颜色,文本字体,样式大小等,这些在我前几篇的博文中有讲解;代码如下所示:

    View Code
    //构造函数
    MyBtn::MyBtn(const QString &strImage,const QString &strInfo,QWidget *parent):QToolButton(parent),
    m_bOver(false),m_bPress(false),m_strImage(strImage),m_strInfo(strInfo)
    {
    //文本颜色
    QPalette objPalette = palette();
    objPalette.setColor(QPalette::ButtonText, QColor(220,220,220));
    setPalette(objPalette);
    //文本粗体
    QFont &objFont = const_cast<QFont &>(font());
    objFont.setWeight(QFont::Bold);
    //样式
    setStyleSheet("QToolButton{border:0px;}");
    //大小
    setIconSize(QSize(TOOLICON_WH,TOOLICON_WH));
    resize(TOOLWIDGET_W,TOOLWIDGET_H);
    setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
    //设置图像文本
    setIcon(QPixmap(strImage));
    setText(strInfo);
    //连接press信号槽,表示按钮按下时
    connect(this,SIGNAL(pressed()),this,SLOT(slot_pressed()));
    }

          OK,按钮的基本效果就出来了,按钮是透明的,只显示图片和文本,没背景信息。
          再一步就是设置鼠标移到按钮上的效果了,鼠标移到按钮上时,背景呈现立体的半透明效果;当鼠标移上去时,设置移动标志(m_bOver)为ture,当鼠标离开按钮时,设置移动标志为false;然后各自update发出重绘事件请求即可。

    View Code
    //enterEvent--鼠标移到按钮上事件
    void MyBtn::enterEvent(QEvent *event)
    {
    SetOver(true);
    }
    //leaveEvent--鼠标离开按钮事件
    void MyBtn::leaveEvent(QEvent *event)
    {
    SetOver(false);
    }
    //SetOver
    void MyBtn::SetOver(bool bEnable)
    {
    if(bEnable!=m_bOver)
    {
    //设置m_bOver标志位
    m_bOver = bEnable;
    //更新
    update();
    }
    }

          在重绘事件里会对bOver进行判断来绘制鼠标移到按钮上的效果,后面讲解到重绘时再细节描述。

          然后就是鼠标单击按钮时的效果了,和鼠标移到按钮上的实现原理基本一样;不过只是在槽函数中而不是由事件触发了;信号和槽函数在构造函数中已经被连接上了,槽函数如下:

    View Code
    //slot_pressed--槽函数
    void MyBtn::slot_pressed()
    {
    SetPress(true);
    emit signal_parent(this);
    }

          其中SetPress函数即设置按下标志(m_bPress)然后发送重绘请求。

    View Code
    //SetPress
    void MyBtn::SetPress(bool bEnable)
    {
    if(bEnable!=m_bPress)
    {
    //设置m_bOver标志位
    m_bPress = bEnable;
    //更新
    update();
    }
    }

          其中slot_pressed槽函数中发送了一个自定义信号signal_parent,在工具栏部件中会对该信号进行连接,其中信号的参数为按钮对象的指针。工具栏部件连接该信号的槽函数为slot_set函数:

    View Code
    //槽函数
    void ToolBar:: slot_set(void *pObject)
    {
    for(int nIndex = 0;nIndex<WIDGET_CNT;++nIndex)
    {
    if(m_listMyBtnPoint.at(nIndex)!=pObject)
    {
    m_listMyBtnPoint.at(nIndex)->SetPress(false);
    }
    }
    }

          总体意思是:例如有A,B,C三个按钮在工具栏中,如果按下了A按钮,这是按下B按钮时,发送信号给工具栏,然后在工具栏对应的槽函数中进行指针值对比,如果不是B按钮,就调用其他对应按钮的SetPress函数,并设置为false,这样A按钮就没有按下去的背景效果了(排他性)。

    三、工具栏按钮效果绘制

          绘制当然要在按钮的paintEvent事件处理函数中实现了,代码如下所示,代码注释的很详细,我就不多说了:

    View Code
    //重绘事件
    void MyBtn::paintEvent(QPaintEvent *event)
    {
    QPainter painter(this);
    //如果按钮被按下
    if(m_bPress)
    {
    //绘制被按下时的效果
    painterinfo(150,200,&painter);
    }
    else if(m_bOver)//如果按钮没有被按下并且鼠标移到按钮上
    {
    //绘制鼠标移到按钮上的按钮效果
    painterinfo(50,100,&painter);
    }
    //调用基类的重绘事件以显示图像文本等
    QToolButton::paintEvent(event);
    }
    //绘制背景渐变
    void MyBtn::painterinfo(int nTopPartOpacity,int nBottomPartOpacity,QPainter *pPainter)
    {
    //设置画笔
    QPen objPen(Qt::NoBrush,1);
    pPainter->setPen(objPen);
    //设置渐变画刷
    QLinearGradient objLinear(rect().topLeft(),rect().bottomLeft());
    //顶部颜色和透明度
    objLinear.setColorAt(0,QColor(150,150,150,nTopPartOpacity));
    //中间颜色和透明度
    objLinear.setColorAt(0.5,QColor(50,50,50,255));
    //底部颜色和透明度
    objLinear.setColorAt(1,QColor(100,100,100,nBottomPartOpacity));
    QBrush objBrush(objLinear);
    pPainter->setBrush(objBrush);
    //画圆角矩形
    pPainter->drawRoundedRect(rect(),5,5);
    }

          OK,这篇博文就写完了,下一篇博文主要讲解标题栏和状态栏的构建了。

  • 相关阅读:
    HTML学习笔记-框架(40)
    HTML学习笔记-使用div和table进行布局(36)
    MVC初体验-EF系列(总结)(23)
    MVC初体验-EF系列(延迟加载)(22)
    MVC初体验-EF系列(状态跟踪的修改)(21)
    MVC初体验-EF系列(CRUD)(20)
    回收站清空后立马恢复
    软件体验记录
    复杂网络,抽象语法树
    PHP修改记录
  • 原文地址:https://www.cnblogs.com/appsucc/p/2417267.html
Copyright © 2020-2023  润新知