admin管理员组文章数量:1548770
Qt之实现360安全卫士主界面(一)
该博文只是模仿360安全卫士的主界面,并不牵涉其中的任何业务功能;重在个人见解以及界面实现;关于360安全卫士的主界面,我想大家都见到过,毕竟基本大部分人都安装过这个软件,基于我对其界面的个人见解,对主界面分割为四部分:分别为标题栏、工具栏、内容区域、状态栏,分割图例如下图所示:
由于标题栏、工具栏、内容区域和状态栏都不是标准的部件,因此只能子类化部件进行自定义开发;主窗口继承于QFrame,而标题栏、工具栏、内容区域与状态栏都继承于QWidget;最后在主窗口中使用QVBoxLayout布局将其他部件加入到该布局中即可,其中标题栏和工具栏以及状态栏都是固定高度的,宽度和内容区域是随窗口缩放而缩放的。
使用Qt实现主界面的效果如下图所示(按【Alt+F4】键退出主界面):
大家可以对比一下,如果在该界面中再添加一些内容,就会越来越像了,后续博文会继续添加内容。
下面讲解具体实现方法,当然方法不只一种,也欢迎各位博友提出自己的看法与实现方式。
1、自定义主窗口
标题栏属于操作系统,我们不能控制标题栏;因此要去掉窗口默认的标题栏,我们使用Qt::FramelessWindowHint窗口样式即可,这样就没有了默认的标题栏,这时需增加我们自定义的标题栏部件即可,再依次增加其他部件到布局中;这些都是很基本的,不多阐述,代码如下:
setWindowFlags(Qt::FramelessWindowHint); //创建标题栏 m_pTitleBar = new TitleBar(this); //创建工具栏 m_pToolBar = new ToolBar(this); //创建内容区域 m_pContentWidget = new ContentWidget(this); //创建状态栏 m_pStatuBar = new StatuBar(this); //创建布局 m_pMainLayout = new QVBoxLayout(this); //将部件加入到布局中 m_pMainLayout->addWidget(m_pTitleBar); m_pMainLayout->addWidget(m_pToolBar); m_pMainLayout->addWidget(m_pContentWidget); m_pMainLayout->addWidget(m_pStatuBar); //设置间距与边缘空白 m_pMainLayout->setSpacing(0); m_pMainLayout->setContentsMargins(0,0,0,0);
2、主窗口背景以及圆角实现
主窗口背景使用图片平铺实现,当然使用Qt的样式表是最为简单方便的了;Qt的样式表格式和css基本一致;如果对css熟悉的话,对Qt的样式表(qss)就会很快熟悉起来;
setStyleSheet("QFrame {background-image:url(:/image/frame.jpg);border:1px solid black;}");
360安全卫士的主界面是圆角的,我们的主界面当然也要实现圆角的了;在主窗口的重绘事件中添加如下代码即可:
//生成一张位图 QBitmap objBitmap(size()); //QPainter用于在位图上绘画 QPainter painter(&objBitmap); //填充位图矩形框(用白色填充) painter.fillRect(rect(),Qt::white); painter.setBrush(QColor(0,0,0)); //在位图上画圆角矩形(用黑色填充) painter.drawRoundedRect(this->rect(),10,10); //使用setmask过滤即可 setMask(objBitmap);
3、主窗口大小
主窗口缩放到一定值之后便不能缩小,所以应该设置其最小宽度和高度;
setMinimumWidth(850); setMinimumHeight(600);
OK,主界面基本看起来有点像样了,当然这个主界面还不能移动,不能缩放,没有工具栏等,这些功能在后续的博文中会阐述添加。
Qt之实现360安全卫士主界面(二)
上一篇博文【Qt之实现360安全卫士主界面(一)】讲解了使用Qt对360安全卫士界面怎么进行分割、布局,如何自定义窗口以及设置窗口背景圆角等,最终形成了一个类似的主界面。但是界面却不能移动,不能伸缩,不能双击最大化还原等;今天该博文就主要讲解这三方面的功能,最终的效果和标准窗口的处理效果一致。效果如下图所示:
一、移动主界面
移动主界面是通过按住鼠标左键进行标题栏拖动最终导致主界面移动;由于还有窗口伸缩功能,因此对于标题栏左部,顶部,右部应该腾出5像素空间给窗口伸缩功能使用,即鼠标移动到这5像素空间之内的话,鼠标形状就会发生改变(暗示可以伸缩窗口);为什么只有标题栏腾出5像素空间,而其他部件(如工具栏、内容区域、状态栏)就不需要了?因为只有标题栏部件重新实现了void mousePressEvent(QMouseEvent *event); void mouseMoveEvent(QMouseEvent *event); void mouseReleaseEvent(QMouseEvent *event);这三个事件;而主窗口也实现了它自己的这三个事件,为了防止界面移动和界面伸缩相冲突,所以留有5像素的空间为窗口伸缩功能使用;下面讲解移动主界面的代码实现:
总体思路是:鼠标按下时设置按下标识并保存按下点坐标;鼠标移动时,判断是否按下(标识)然后获得移动鼠标点的坐标,根据两者的差值最后移动主界面即可;当然,鼠标释放时肯定要重置按下标识。
//鼠标按下事件 void TitleBar::mousePressEvent(QMouseEvent *event) { if (event->button() == Qt::LeftButton) { if(event->y()<VALUE_DIS||event->x()<VALUE_DIS||rect().width()-event->x()<5) { event->ignore(); return; } m_ptPress = event->globalPos(); m_bLeftButtonPress = true; } event->ignore(); } //鼠标移动事件 void TitleBar::mouseMoveEvent(QMouseEvent *event) { if(m_bLeftButtonPress) { m_ptMove = event->globalPos(); //移动主窗口 MainWindow *pMainWindow = (qobject_cast<MainWindow *>(parent())); pMainWindow->move(pMainWindow->pos()+m_ptMove-m_ptPress); //重新设置m_ptPress; m_ptPress = m_ptMove; } event->ignore(); } //鼠标释放事件 void TitleBar::mouseReleaseEvent(QMouseEvent *event) { if (event->button() == Qt::LeftButton) { m_bLeftButtonPress = false; } event->ignore(); }
注意,在事件的末尾要加上event->ignore();语句,因为标题栏是覆盖在主界面部件之上的,所以事件传递是先传递给标题栏,标题栏完成该事件之后,应使用event->ignore();表示继续将事件传递给其父对象(即主界面部件);
二、伸缩主界面
界面当然要可以伸缩,即窗口变大变小,这些也是由鼠标事件产生的,也是三个事件处理代码;当鼠标移动到主界面内部周围5像素时,改变鼠标形状;当进行伸缩拖动时,根据拖动方向进行主界面的位置和大小设置即可。
//鼠标按下事件 void MainWindow::mousePressEvent(QMouseEvent *event) { if (event->button() == Qt::LeftButton) { m_ptPressGlobal = event->globalPos(); m_bLeftBtnPress = true; } } //鼠标移动事件 void MainWindow::mouseMoveEvent(QMouseEvent *event) { if(!m_bLeftBtnPress) { m_eDirection = PointValid(event->x(),event->y()); SetCursorStyle(m_eDirection); } else { int nXGlobal = event->globalX(); int nYGlobal = event->globalY(); SetDrayMove(nXGlobal,nYGlobal,m_eDirection); m_ptPressGlobal =QPoint(nXGlobal,nYGlobal); } } //鼠标释放事件 void MainWindow::mouseReleaseEvent(QMouseEvent *event) { if (event->button() == Qt::LeftButton) { m_bLeftBtnPress = false; m_eDirection = eNone; } } //鼠标双击事件 void MainWindow::mouseDoubleClickEvent(QMouseEvent *event) { if (event->button() == Qt::LeftButton && event->y()<= m_pTitleBar->height()) { if(!m_bMaxWin) { m_rectRestoreWindow = geometry(); setGeometry(qApp->desktop()->availableGeometry()); } else { setGeometry(m_rectRestoreWindow); } m_bMaxWin = !m_bMaxWin; } }
其中设置鼠标形状的代码如下:
View Code//设置鼠标样式 void MainWindow::SetCursorStyle(enum_Direction direction) { //设置上下左右以及右上、右下、左上、坐下的鼠标形状 switch(direction) { case eTop: case eBottom: setCursor(Qt::SizeVerCursor); break; case eRight: case eLeft: setCursor(Qt::SizeHorCursor); break; case eTopRight: case eBottomLeft: setCursor(Qt::SizeBDiagCursor); break; case eRightBottom: case eLeftTop: setCursor(Qt::SizeFDiagCursor); break; default: setCursor(Qt::ArrowCursor); break; } }
伸缩窗口的位置信息设置代码如下:
View Code//设置鼠标拖动的窗口位置信息 void MainWindow::SetDrayMove(int nXGlobal,int nYGlobal,enum_Direction direction) { //计算偏差 int ndX = nXGlobal - m_ptPressGlobal.x(); int ndY = nYGlobal - m_ptPressGlobal.y(); //获得主窗口位置信息 QRect rectWindow = geometry(); //判别方向 if(direction & eTop) { rectWindow.setTop(rectWindow.top()+ndY); } if(direction & eRight) { rectWindow.setRight(rectWindow.right()+ndX); } if(direction & eBottom) { rectWindow.setBottom(rectWindow.bottom()+ndY); } if(direction & eLeft) { rectWindow.setLeft(rectWindow.left()+ndX); } if(rectWindow.width()< minimumWidth() || rectWindow.height()<minimumHeight()) { return; } //重新设置窗口位置为新位置信息 setGeometry(rectWindow); }
三、双击最大化和还原
这个功能处理起来很简单,只要重新实现void mouseDoubleClickEvent(QMouseEvent *event)事件即可并且限制有效范围,即在不超过标题栏高度的像素空间范围内双击才有效:
//鼠标双击事件 void MainWindow::mouseDoubleClickEvent(QMouseEvent *event) { if (event->button() == Qt::LeftButton && event->y()<= m_pTitleBar->height()) { if(!m_bMaxWin) { m_rectRestoreWindow = geometry(); setGeometry(qApp->desktop()->availableGeometry()); } else { setGeometry(m_rectRestoreWindow); } m_bMaxWin = !m_bMaxWin; } }使用QDesktopWidget类的availableGeometry()函数可排除任务栏(桌面)所占空间。
Qt之实现360安全卫士主界面(三)
这篇博文主要讲述360安全卫士工具栏的创建;工具栏由图片和文字组成,当鼠标移到工具栏按钮上时,需要有些特征表达该现象,如背景色变化等;当然鼠标单击工具栏按钮时,同样也要有些特征,并且这个特征区别于鼠标移到按钮上的特征;写起来有些拗口,我给大家先看看我实现的效果图。
单击按钮时和鼠标移到按钮上时,按钮背景会不同,并且单击其他按钮时,已单击的那个按钮背景应该恢复。下面讲解其具体实现。
一、工具栏的创建
工具栏当然是自定义的部件了(继承于QWidget),工具栏上的那些按钮都是继承于QToolButton;其中有9个按钮,最右边的是label;工具栏类的成员变量如下所示:
View CodeQList<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发出重绘事件请求即可。
//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,这篇博文就写完了,下一篇博文主要讲解标题栏和状态栏的构建了。
Qt之实现360安全卫士主界面(四)
这篇博文主要讲解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")) { //连接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 Codevoid 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(); } }
上述代码实现是发送自定义信号;状态栏部分由于很简单就不描述了。
版权声明:本文标题:Qt之实现360安全卫士主界面(转) 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:https://m.elefans.com/dongtai/1727218499a1103305.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论