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

长平狐 发布于 2012/11/06 18:08
阅读 1K+
收藏 1
Qt

      这篇博文主要讲解360安全卫士标题栏的创建。关于标题栏,我想大家应该都非常熟悉了,其主要包括窗口关闭、最大化/还原、最小化等按钮;但是标题栏的这些按钮都是非常有特色的。

      在我写这篇博文之前,我就已经完成了类似360安全卫士标题栏的创建代码,在开始写代码时,我仔细想了想360安全卫士主界面标题栏的构建方法,它是自绘的还是贴图的?所以我特意在360论坛查了查它皮肤制作的方法,并在它的安装目录下的找到了这些按钮的特定图片(皮肤文件解压),即由贴图来做的。

      既然知道了构建方法,那么就用代码实现即可,我实现的效果图如下(初始界面是这样,标题栏的其他效果和360安全卫士的标题栏效果一样):

      标题栏也是自定义的部件(继承于QWidget),在这个自定义的部件里,你想实现啥功能都可以。

一、部件构建

      部件构建当然是创建子部件,设置子部件样式,给标题栏设置布局管理等,这些也都是很基础的。

      标题栏由三个QLabel和五个QToolButton组成,这五个QToolButton即为标题栏最右边的五个功能按钮,首先当然是创建这些子部件了。

View Code
// 创建子部件
void TitleBar::CreateWidget()
{
// 图像标签--logo
m_pLabelIcon = new QLabel( this);
QPixmap objPixmap( " :/image/360AboutLogo.png ");
m_pLabelIcon->setPixmap(objPixmap.scaled(TITLE_H,TITLE_H));
// 文本标签--标题
m_pLabelTitle = new QLabel( this);
m_pLabelTitle->setText(QString( " 360 Safe Guard V8.5 "));
// 文本标签--样式版本
m_pLabelVersion = new QLabel( this);
m_pLabelVersion->setText(QString( " Use Class Style "));
// 设置鼠标形状
m_pLabelVersion->setCursor(Qt::PointingHandCursor);
// 按钮--更换皮肤
m_pBtnSkin = new QToolButton( this);
// 设置初始图片
SetBtnIcon(m_pBtnSkin,eBtnStateDefault, true);
// 按钮--菜单
m_pBtnMenu = new QToolButton( this);
SetBtnIcon(m_pBtnMenu,eBtnStateDefault, true);
// 按钮--最小化
m_pBtnMin = new QToolButton( this);
SetBtnIcon(m_pBtnMin,eBtnStateDefault, true);
// 按钮--最大化/还原
m_pBtnMax = new QToolButton( this);
SetBtnIcon(m_pBtnMax,eBtnStateDefault, true);
// 按钮--关闭
m_pBtnClose = new QToolButton( this);
SetBtnIcon(m_pBtnClose,eBtnStateDefault, true);
// 获得子部件
const QObjectList &objList = children();
for( int nIndex= 0; nIndex<objList.count();++nIndex)
{
// 设置子部件的MouseTracking属性
((QWidget*)(objList.at(nIndex)))->setMouseTracking( true);
// 如果是QToolButton部件
if( 0==qstrcmp(objList.at(nIndex)->metaObject()->className(), " QToolButton "))
{
// 连接ssed信号为slot_btnss
connect(((QToolButton*)(objList.at(nIndex))),SIGNAL(ssed()), this,SLOT(slot_btnss()));
// 连接clicked信号为slot_btnclick
connect(((QToolButton*)(objList.at(nIndex))),SIGNAL(clicked()), this,SLOT(slot_btnclick()));
// 设置顶部间距
((QToolButton*)(objList.at(nIndex)))->setContentsMargins( 0,VALUE_DIS, 0, 0);
}
}
}

      子部件创建完之后,就要设置这些子部件的基本样式了,我使用qss样式表对其进行样式设置,当然还有其他方法。

View Code
// 设置子部件样式(qss)
void TitleBar::SetWidgetStyle()
{
// 设置标签的文本颜色,大小等以及按钮的边框
setStyleSheet( " QLabel{color:#CCCCCC;font-size:12px;font-weight:bold;}QToolButton{border:0px;} ");
// 设置左边距
m_pLabelTitle->setStyleSheet( " margin-left:6px; ");
// 设置右边距以及鼠标移上去时的文本颜色
m_pLabelVersion->setStyleSheet( " QLabel{margin-right:10px;}QLabel:hover{color:#00AA00;} ");
}

      最后就是创建布局管理器,把这些子部件加入到布局管理器中,我使用水平布局管理器,如下代码所示:

View Code
// 创建设置布局
void TitleBar::CreateLayout()
{
// 水平布局
m_pLayout = new QHBoxLayout( this);
// 添加部件
m_pLayout->addWidget(m_pLabelIcon);
m_pLayout->addWidget(m_pLabelTitle);
// 添加伸缩项
m_pLayout->addStretch( 1);
// 添加部件
m_pLayout->addWidget(m_pLabelVersion);
m_pLayout->addWidget(m_pBtnSkin);
m_pLayout->addWidget(m_pBtnMenu);
m_pLayout->addWidget(m_pBtnMin);
m_pLayout->addWidget(m_pBtnMax);
m_pLayout->addWidget(m_pBtnClose);
// 设置Margin
m_pLayout->setContentsMargins( 0, 0,VALUE_DIS, 0);
// 设置部件之间的space
m_pLayout->setSpacing( 0);
setLayout(m_pLayout);
}

      在这节中,设置按钮图片的函数为SetBtnIcon函数,该函数的原型如下所示:

View Code
void SetBtnIcon(QToolButton *pBtn,eBtnMoustState state, bool bInit= false);

      其中pBtn代表被设置图片的按钮,而eBtnMoustState是一个枚举值,代表该按钮当前的状态,枚举定义如下所示:

View Code
// 枚举,按钮状态
enum eBtnMoustState{
eBtnStateNone, // 无效
eBtnStateDefault, // 默认值(如按钮初始显示)
eBtnStateHover, // 鼠标移到按钮上状态
eBtnStatePress // 鼠标按下按钮时状态
};

      而bInit表示是否是初始化设置,因为在SetBtnIcon函数里需要获得主界面最大化标志值,而这时候主界面窗口构造函数还没完成,同时在SetBtnIcon函数里又需要获得主界面窗口对象,因此会矛盾,所以使用了bInit标志值进行区分。

      SetBtnIcon函数的定义如下代码所示:

View Code
// 设置按钮不同状态下的图标
void TitleBar::SetBtnIcon(QToolButton *pBtn,eBtnMoustState state, bool bInit /* =false */)
{
// 获得图片路径
QString strImagePath = GetBtnImagePath(pBtn,bInit);
// 创建QPixmap对象
QPixmap objPixmap(strImagePath);
// 得到图像宽和高
int nPixWidth = objPixmap.width();
int nPixHeight = objPixmap.height();
// 如果状态不是无效值
if(state!=eBtnStateNone)
{
/* 设置按钮图片
按钮的图片是连续在一起的,如前1/4部分表示默认状态下的图片部分,接后的1/4部分表示鼠标移到按钮状态下的图片部分
*/
pBtn->setIcon(objPixmap.copy((nPixWidth/ 4)*(state- 1), 0,nPixWidth/ 4,nPixHeight));
// 设置按钮图片大小
pBtn->setIconSize(QSize(nPixWidth/ 4,nPixHeight));
}
}
View Code
// 获得图片路径(固定值)
const QString TitleBar::GetBtnImagePath(QToolButton *pBtn, bool bInit /* =false */)
{
QString strImagePath;
// 皮肤按钮
if(m_pBtnSkin==pBtn)
{
strImagePath = " :/image/SkinButtom.png ";
}
// 菜单按钮
if(m_pBtnMenu==pBtn)
{
strImagePath = " :/image/title_bar_menu.png ";
}
// 最小化
if(m_pBtnMin==pBtn)
{
strImagePath = " :/image/sys_button_min.png ";
}
// 最大化/还原按钮,所以包括最大化和还原两张图片
if(m_pBtnMax==pBtn)
{
// 如果是初始设置或者主界面的最大化标志不为真(其中MainWindow::Instance()使用单例设计模式)
if(bInit== true || MainWindow::Instance()->GetMaxWin()== false)
{
// 最大化按钮图片路径
strImagePath = " :/image/sys_button_max.png ";
}
else
{
// 还原按钮图片路径
strImagePath = " :/image/sys_button_restore.png ";
}
}
// 关闭按钮
if(m_pBtnClose==pBtn)
{
strImagePath = " :/image/sys_button_close.png ";
}
return strImagePath;
}

二、设置按钮其他效果

      各位在使用360安全卫士的时候,把鼠标移到关闭按钮上或者使用鼠标按下关闭按钮,其呈现不同的图片以示区分,当然其他按钮也一样。那么是不是也和工具栏按钮一样,子类化一个按钮了?不需要。使用事件过滤器,在标题栏部件中进行事件判断和目标判断即可。

      首先是创建事件过滤器,代码如下所示:

View Code
// 创建事件过滤器
void TitleBar::CreateEventFiter()
{
m_pBtnSkin->installEventFilter( this);
m_pBtnMenu->installEventFilter( this);
m_pBtnMin->installEventFilter( this);
m_pBtnMax->installEventFilter( this);
m_pBtnClose->installEventFilter( this);
}

      然后在标题栏部件中重写eventFilter函数即可,代码如下:

View Code
// 事件过滤
bool TitleBar::eventFilter(QObject *obj, QEvent * event)
{
// 按钮状态
eBtnMoustState eState = eBtnStateNone;
// 判断事件类型--QEvent::Enter
if ( event->type() == QEvent::Enter)
{
eState = eBtnStateHover;
}
// 判断事件类型--QEvent::Leave
if ( event->type() == QEvent::Leave)
{
eState = eBtnStateDefault;
}
// 判断事件类型--QEvent::MouseButtonPress
if ( event->type() == QEvent::MouseButtonPress && ((QMouseEvent*)( event))->button()== Qt::LeftButton)
{
eState = eBtnStatePress;
}
// 判断目标
if(m_pBtnSkin==obj || m_pBtnMenu==obj || m_pBtnMin==obj || m_pBtnMax==obj || m_pBtnClose==obj)
{
// 如果状态有效
if(eState != eBtnStateNone)
{
// 根据状态设置按钮图标
SetBtnIcon((QToolButton *)obj,eState);
return false;
}
}
return QWidget::eventFilter(obj, event);
}

      即根据事件类型设置按钮状态;最后在各个按钮的click槽函数中实现相应功能即可,如窗口关闭,最大化等。

View Code
// 槽函数--slot_btnclick
void TitleBar::slot_btnclick()
{
QToolButton *pBtn = (QToolButton*)(sender());
if(pBtn==m_pBtnMin)
{
emit signal_min();
}
if(pBtn==m_pBtnMax)
{
emit signal_maxrestore();
}
if(pBtn==m_pBtnClose)
{
emit signal_close();
}
}

      上述代码实现是发送自定义信号;状态栏部分由于很简单就不描述了。

      我把二进制文件打包供下载,希望大家提出意见,有什么不对的地方望指教;下载地址为:文件下载


原文链接:http://www.cnblogs.com/appsucc/archive/2012/03/28/2421225.html
加载中
返回顶部
顶部