上一篇博文【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;
}
}
其中设置鼠标形状的代码如下:
//设置鼠标样式
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;
}
}
伸缩窗口的位置信息设置代码如下:
//设置鼠标拖动的窗口位置信息
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()函数可排除任务栏(桌面)所占空间。