Qt之实现360安全卫士主界面
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
动到主界面内部周围 5 像素时,改变鼠标形状;当进行伸缩拖动时,根据拖动方向进行主界面的位置和大 小设置即可。
复制代码
1. //鼠标按下事件
void MainWindow::mousePressEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton)
m_rectRestoreWindow = geometry(); setGeometry(qApp->desktop()->availableGeometry()); } else { setGeometry(m_rectRestoreWindow); } m_bMaxWin = !m_bMaxWin; } } 其中设置鼠标形状的代码如下: 复制代码 1. //设置鼠标样式 void MainWindow::SetCursorStyle(enum_Direction direction) { //设置上下左右以及右上、右下、左上、坐下的鼠标形状 switch(direction) { case eTop: case eBottom: setCursor(Qt::SizeVerCursor); break; case eRight: case eLeft: setCursor(Qt::SizeHorCursor); break;
SetCursorStyle(m_eDirection);
}
else
{
int nXGlobal = event->globalX();
int nYGlobal = event->globalY();
SetDrayMove(nXGlobal,nYGlobal,m_eDirection);
m_ptPressGlobal =QPoint(nXGlobal,nYGlobal);
} 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(); }
} } //鼠标释放事件 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) {
注意,在事件的末尾要加上 event->ignore();语句,因为标题栏是覆盖在主界面部件之上的,所以事件传 递是先传递给标题栏,标题栏完成该事件之后,应使用 event->ignore();表示继续将事件传递给其父对象(即 主界面部件); 二、伸缩主界面
界面当然要可以伸缩,即窗口变大变小,这些也是由鼠标事件产生的,也是三个事件处理代码;当鼠标移
效果一致。效果如下图所示:
一、移动主界面 移动主界面是通过按住鼠标左键进行标题栏拖动最终导致主界面移动;由于还有窗口伸缩功能,因此对于 标题栏左部,顶部,右部应该腾出 5 像素给窗口伸缩功能使用,即鼠标移动到这 5 像素之内的话,鼠标形 状就会发生改变(暗示可以伸缩窗口);为什么只有标题栏腾出 5 像素空间,而其他部件(如工具栏、内容区 域、状态栏)就不需要了?因为只有标题栏部件重新实现了 void mousePressEvent(QMouseEvent *event); void mouseMoveEvent(QMouseEvent *event); void mouseReleaseEvent(QMouseEvent *event);这三 个事件;而主窗口也实现了它自己的这三个事件,为了防止界面移动和界面伸缩相冲突,所以留有 5 像素 的空间为窗口伸缩功能使用;下面讲解移动主界面的代码实现: 总体思路是:鼠标按下时设置按下标识并保存按下点坐标;鼠标移动时,判断是否按下(标识)然后获得移 动鼠标点的坐标,根据两者的差值最后移动主界面即可;当然,鼠标释放时肯定要重置按下标识。 //鼠标按下事件 void TitleBar::mousePressEvent(QMouseEvent *event) {
该博文只是模仿 360 安全卫士的主界面,并不牵涉其中的任何业务功能;重在个人见解以及界面实现;关 于 360 安全卫士的主界面,我想大家都见到过,毕竟基本大部分人都安装过这个软件,基于我对其界面的 个人见解,对主界面分割为四部分:分别为标题栏、工具栏、内容区域、状态栏,分割图例如下图所示:
由于标题栏、工具栏、内容区域和状态栏都不是标准的部件,因此只能子类化部件进行自定义开发;主窗 口继承于 QFrame,而标题栏、工具栏、内容区域与状态栏都继承于 QWidget;最后在主窗口中使用 QVB oxLayout 布局将其他部件加入到该布局中即可,其中标题栏和工具栏以及状态栏都是固定高度的,宽度和 内容区域是随窗口缩放而缩放的。使用 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);
3、主窗口大小 主窗口缩放到一定值之后便不能缩小,所以应该设置其最小宽度和高度; setMinimumWidth(850); setMinimumHeight(600);
OK,主界面基本看起来有点像样了,当然这个主界面还不能移动,不能缩放,没有工具栏等,这些功能在 后续的博文中会阐述添加。 上一篇博文【Qt 之实现 360 安全卫士主界面(一) 】讲解了使用 Qt 对 360 安全卫士界面怎么进行分割、布 局,如何自定义窗口以及设置窗口背景圆角等,最终形成了一个类似的主界面。但是界面却不能移动,不 能伸缩,不能双击最大化还原等;今天该博文就主要讲解这三方面的功能,最终的效果和标准窗口的处理
{
m_ptPressGlobal = event->globalPos();
m_bLeftBtnPress = true;
}
} //鼠标移动事件
void MainWindow::mouseMoveEvent(QMouseEvent *event)
{
if(!m_bLeftBtnPress)
{
m_eDirection = PointValid(event->x(),event->y());
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;
case eTopRight: case eBottomLeft:
setCursor(Qt::SizeBDiagCursor); break; case eRightBottom: case eLeftTop: setCursor(Qt::SizeFDiagCursor); break; default: setCursor(Qt::ArrowCursor); break; } } 伸缩窗口的位置信息设置代码如下: 复制代码 1. //设置鼠标拖动的窗口位置信息 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; }
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);
复制代码
1. //鼠标按下事件
void MainWindow::mousePressEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton)
m_rectRestoreWindow = geometry(); setGeometry(qApp->desktop()->availableGeometry()); } else { setGeometry(m_rectRestoreWindow); } m_bMaxWin = !m_bMaxWin; } } 其中设置鼠标形状的代码如下: 复制代码 1. //设置鼠标样式 void MainWindow::SetCursorStyle(enum_Direction direction) { //设置上下左右以及右上、右下、左上、坐下的鼠标形状 switch(direction) { case eTop: case eBottom: setCursor(Qt::SizeVerCursor); break; case eRight: case eLeft: setCursor(Qt::SizeHorCursor); break;
SetCursorStyle(m_eDirection);
}
else
{
int nXGlobal = event->globalX();
int nYGlobal = event->globalY();
SetDrayMove(nXGlobal,nYGlobal,m_eDirection);
m_ptPressGlobal =QPoint(nXGlobal,nYGlobal);
} 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(); }
} } //鼠标释放事件 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) {
注意,在事件的末尾要加上 event->ignore();语句,因为标题栏是覆盖在主界面部件之上的,所以事件传 递是先传递给标题栏,标题栏完成该事件之后,应使用 event->ignore();表示继续将事件传递给其父对象(即 主界面部件); 二、伸缩主界面
界面当然要可以伸缩,即窗口变大变小,这些也是由鼠标事件产生的,也是三个事件处理代码;当鼠标移
效果一致。效果如下图所示:
一、移动主界面 移动主界面是通过按住鼠标左键进行标题栏拖动最终导致主界面移动;由于还有窗口伸缩功能,因此对于 标题栏左部,顶部,右部应该腾出 5 像素给窗口伸缩功能使用,即鼠标移动到这 5 像素之内的话,鼠标形 状就会发生改变(暗示可以伸缩窗口);为什么只有标题栏腾出 5 像素空间,而其他部件(如工具栏、内容区 域、状态栏)就不需要了?因为只有标题栏部件重新实现了 void mousePressEvent(QMouseEvent *event); void mouseMoveEvent(QMouseEvent *event); void mouseReleaseEvent(QMouseEvent *event);这三 个事件;而主窗口也实现了它自己的这三个事件,为了防止界面移动和界面伸缩相冲突,所以留有 5 像素 的空间为窗口伸缩功能使用;下面讲解移动主界面的代码实现: 总体思路是:鼠标按下时设置按下标识并保存按下点坐标;鼠标移动时,判断是否按下(标识)然后获得移 动鼠标点的坐标,根据两者的差值最后移动主界面即可;当然,鼠标释放时肯定要重置按下标识。 //鼠标按下事件 void TitleBar::mousePressEvent(QMouseEvent *event) {
该博文只是模仿 360 安全卫士的主界面,并不牵涉其中的任何业务功能;重在个人见解以及界面实现;关 于 360 安全卫士的主界面,我想大家都见到过,毕竟基本大部分人都安装过这个软件,基于我对其界面的 个人见解,对主界面分割为四部分:分别为标题栏、工具栏、内容区域、状态栏,分割图例如下图所示:
由于标题栏、工具栏、内容区域和状态栏都不是标准的部件,因此只能子类化部件进行自定义开发;主窗 口继承于 QFrame,而标题栏、工具栏、内容区域与状态栏都继承于 QWidget;最后在主窗口中使用 QVB oxLayout 布局将其他部件加入到该布局中即可,其中标题栏和工具栏以及状态栏都是固定高度的,宽度和 内容区域是随窗口缩放而缩放的。使用 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);
3、主窗口大小 主窗口缩放到一定值之后便不能缩小,所以应该设置其最小宽度和高度; setMinimumWidth(850); setMinimumHeight(600);
OK,主界面基本看起来有点像样了,当然这个主界面还不能移动,不能缩放,没有工具栏等,这些功能在 后续的博文中会阐述添加。 上一篇博文【Qt 之实现 360 安全卫士主界面(一) 】讲解了使用 Qt 对 360 安全卫士界面怎么进行分割、布 局,如何自定义窗口以及设置窗口背景圆角等,最终形成了一个类似的主界面。但是界面却不能移动,不 能伸缩,不能双击最大化还原等;今天该博文就主要讲解这三方面的功能,最终的效果和标准窗口的处理
{
m_ptPressGlobal = event->globalPos();
m_bLeftBtnPress = true;
}
} //鼠标移动事件
void MainWindow::mouseMoveEvent(QMouseEvent *event)
{
if(!m_bLeftBtnPress)
{
m_eDirection = PointValid(event->x(),event->y());
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;
case eTopRight: case eBottomLeft:
setCursor(Qt::SizeBDiagCursor); break; case eRightBottom: case eLeftTop: setCursor(Qt::SizeFDiagCursor); break; default: setCursor(Qt::ArrowCursor); break; } } 伸缩窗口的位置信息设置代码如下: 复制代码 1. //设置鼠标拖动的窗口位置信息 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; }
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);