Qt完美实现360安全卫士主界面标题栏

关于标题栏,我想大家应该都非常熟悉了,其主要包括窗口关闭、最大化/还原、最小化等按钮;但是标题栏的这些按钮都是非常有
【菜科解读】
这篇博文主要讲解360安全卫士标题栏的创建。
关于标题栏,我想大家应该都非常熟悉了,其主要包括窗口关闭、最大化/还原、最小化等按钮;但是标题栏的这些按钮都是非常有特色的。
在我写这篇博文之前,我就已经完成了类似360安全卫士标题栏的创建代码,在开始写代码时,我仔细想了想360安全卫士主界面标题栏的构建方法,它是自绘的还是贴图的?所以我特意在360论坛查了查它皮肤制作的方法,并在它的安装目录下的找到了这些按钮的特定图片(皮肤文件解压),即由贴图来做的。
既然知道了构建方法,那么就用代码实现即可,我实现的效果图如下(初始界面是这样,标题栏的其他效果和360安全卫士的标题栏效果一样):
标题栏也是自定义的部件(继承于QWidget),在这个自定义的部件里,你想实现啥功能都可以。
一、部件构建
部件构建当然是创建子部件,设置子部件样式,给标题栏设置布局管理等,这些也都是很基础的。
标题栏由三个QLabel和五个QToolButton组成,这五个QToolButton即为标题栏最右边的五个功能按钮,首先当然是创建这些子部件了。
//创建子部件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; nIndexsetMouseTracking(true); //如果是QToolButton部件 if(0==qstrcmp(objList.at(nIndex)->metaObject()->className(),"QToolButton")) //连接pressed信号为slot_btnpress connect(((QToolButton*)(objList.at(nIndex))),SIGNAL(pressed()),this,SLOT(slot_btnpress())); //连接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_btnclickvoid 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();}
上述代码实现是发送自定义信号;状态栏部分由于很简单就不描述了。
完美,实现,360,安全,卫士,主,界面,标题栏,这篇,斯鲁伊斯海战后 法国入侵英国的野心都没有机会实现
这场英法之间的战争发生在斯鲁伊斯,现位于比利时和荷兰之间。
参与斯鲁伊斯海战的法国舰队在爱德华三世给儿子的信中有所提及。
斯鲁伊斯海战图片 这支舰队总共有一百九十艘战船,还有一部分热那亚佣军,总数为两万人。
英国历史一直声称英国舰队不管是人员还是船只数量都大大少于法国舰队。
但当英国舰队航时,一共有两百艘战船。
在半路中,一支拥有五十艘船的舰队又加入了英国海军。
在这支舰队中,大部分人员没有经过训练。
英国舰队的船只数量在两外五十艘左右,士兵约有两万人。
法国国王将舰队分成三路,并用铁链将船只连起来。
英国舰队抵达海湾时,因为逆光逆流的缘故,停船等待时机。
流向改变后,英国舰队占领占地,开始射击。
法国舰队机动性较差,没有弓箭手和盔甲,受到了英国舰队的欺负。
经过八小时的激战,法国舰队被击败,再无斗志,四下逃窜。
法国舰队惨败,损失战船近一百八十艘,牺牲了近两万名士兵。
法国舰队的两个指挥官,一个战死沙场,一个回国被处以绞刑。
英国舰队在这次战争中伤亡了四千人,数量远远小于法国。
斯鲁伊斯海战也被称为斯勒伊斯海战。
在这场海战中,法国遭受了巨大的打击,法国入侵英国的野心没有机会实现。
这就是斯鲁伊斯海战简介。
斯鲁伊斯海战结果 斯鲁伊斯海战结果是英国取得了最后的胜利。
在这场战役中,法国舰队付出了惨烈的代价。
英国历载,英国舰队花费了很少的代价就打败了法国,并歼敌两万人。
这个数据可能不太正确。
斯鲁伊斯海战结束后,英国舰队停止了行动,这显示出了当时的英国也遭到了一部分损失,需要原地休整。
斯鲁伊斯海战图片 英国得到了这次战役的胜利,从此强大的英国海军以绝对的优势掌握了英吉利海峡。
法国舰队惨败,损失了一百八十艘战船。
法国舰队两个指挥官最终都在劫难逃,只有雇佣军的首领逃脱一劫。
英国在与法国的海战中首战告捷,为日后进犯法国创造了先决条件。
法国舰队再也不能跨入英吉利海峡作战,此后绝大多数英法之间的战争到在法国本土发生。
双方在军乐声中交战。
在开展前,爱德华曾经从临近的城镇中召集拥护他的人前来主战。
按照英国史学家的记载,那些人全部到达,乘着小船从后面偷袭法军。
法国舰队指挥见大势已去,率领船队逃亡公海,躲过了屠杀。
第一列战队战败后,法军放弃了所有希望。
第二、三列人员纷纷逃亡。
可是船只被铁链连在一起,许多都挤翻了。
按爱德华的口述,直至深夜,法国的舰队全被全部歼灭。
斯鲁伊斯战争结束后,爱德华设宴庆祝。
三百名神父在圣母大教堂举行了盛大的弥撒。
斯鲁伊斯战役从战术上来看,是英国海军空前的胜利,在下一代英国都保有制海权。
这就是斯鲁伊斯海战结果。
随机文章淫欲魔王阿斯莫德,诱骗俊美人类关至第二层地狱(至上四柱之一)近期太平洋火山地震连发,两天发生两次地震一次火山爆发(活跃期)被加蓬蝰蛇咬了有救吗,有救/但被咬的部位100%会被截肢挪威NSM精确制导导弹,曾受到F35青睐(制导方式奇特)揭秘河南洛阳盗墓大案,疯狂盗墓贼用火药炸开皇后陵盗掘国宝
便携式电脑读卡器,轻松实现数据传输
现代社会,数据传输已经成为人们生活中不可或缺的一部分。
然而,传输数据的过程常常会遇到一些困难,比如电脑和手机之间的连接问题,或者是数据线太短无法满足需求等等。
为了解决这些问题,便携式电脑读卡器应运而生。
它不仅可以轻松实现电脑和手机之间的数据传输,还具有便携性强、操作简单等优点,为人们的生活带来了极大的便利。
工具原料:品牌型号:SanDisk Ultra Dual Drive m3.0操作系统版本:Windows 10软件版本:SanDisk Memory Zone一、便携性强1、小巧轻便:便携式电脑读卡器体积小巧,重量轻,方便携带。
2、无需电源:便携式电脑读卡器通过USB接口供电,无需外接电源,使用更加方便。
二、操作简单1、插入读卡器:将便携式电脑读卡器插入电脑的USB接口。
2、连接手机:将手机通过数据线连接到读卡器的另一端。
3、传输数据:打开SanDisk Memory Zone软件,选择要传输的文件,点击传输按钮即可完成数据传输。
三、高速传输1、USB 3.0接口:便携式电脑读卡器采用USB 3.0接口,传输速度更快,节省时间。
2、支持多种格式:便携式电脑读卡器支持多种格式的文件传输,包括照片、视频、音乐等。
总结:便携式电脑读卡器是一种非常实用的工具,它可以轻松实现电脑和手机之间的数据传输,具有便携性强、操作简单、高速传输等优点。
在现代社会中,数据传输已经成为人们生活中不可或缺的一部分,便携式电脑读卡器的出现为人们的生活带来了极大的便利。
未来,随着科技的不断发展,便携式电脑读卡器可能会进一步提升传输速度,支持更多的文件格式,为人们的数据传输提供更加便捷的解决方案。