1.实现的功能
窗口的 最大化和最大化前大小切换、最小化、关闭窗口、移动、拉伸、缩小。
很多时候,为了界面的美观,需要将界面设置为无边框窗口,这就需要重写上述功能来完善窗口。
2.具体步骤
最大化、最小化、关闭 为三个按钮,按钮设置好布局位置,设置QIcon,将按钮添加入槽,具体步骤不在此叙述。
以下三个槽函数即为最大化、最小化、关闭三个按钮的槽函数;
私有变量中的变量和函数看注释和具体代码。
private slots:
void on_minBtn_clicked();
void on_closeBtn_clicked();
void on_maxBtn_clicked();
private:
Ui::RailwayPowerInterface *ui;
bool _isleftpressed = false; //判断是否是左键点击
int _curpos = 0; //鼠标左键按下时光标所在区域
QPoint _plast; //获取鼠标左键按下时光标在全局(屏幕而非窗口)的位置
void mousePressEvent(QMouseEvent* event);//鼠标按下事件
void mouseReleaseEvent(QMouseEvent* event);//鼠标释放事件
void mouseMoveEvent(QMouseEvent* event);//鼠标移动事件
int countRow(QPoint p); //获取光标在窗口所在区域的 行 返回行数
int countFlag(QPoint p,int row); //获取光标在窗口所在区域的 列 返回行列坐标
void setCursorType(int flag); //根据传入的坐标,设置光标样式
窗口最大化、最小化、关闭的具体实现代码,比较简单
//最小化界面
void RailwayPowerInterface::on_minBtn_clicked()
{
this->showMinimized();
}
//关闭界面
void RailwayPowerInterface::on_closeBtn_clicked()
{
this->close();
}
//放大,缩小界面
void RailwayPowerInterface::on_maxBtn_clicked()
{
static bool max = false;
static QRect location = this->geometry();
if (max) {
this->setGeometry(location);//回复窗口原大小和位置
ui->maxBtn->setIcon(QIcon(":/MAX_.png"));
}else {
ui->maxBtn->setIcon(QIcon(":/minMAX.png"));
location = this->geometry(); //最大化前记录窗口大小和位置
//this->setGeometry(qApp->desktop()->availableGeometry());
this->showFullScreen(); //设置窗口铺满全屏
}
max = !max;
}
在设置窗口 可伸缩、可移动前,需要线分析以下窗口;
如图,可将窗口分为如下9部分,光标在不同区域将呈现不同样式,而根据光标样式又可以将以下9个区域分为五类:
(1,1) (3,3) :
(1,2) (3,2) :
(1,3) (3,3) :
(2,1) (2,3) :
(2,2) :以上区域用来伸缩窗口,此区域用来移动窗口
注: 在代码中,将坐标(1,1) 以数字 11代替,(1,2)以数字12代替,其他坐标依次类推。
通过宏定义来设定边框区域的大小(即绿色区域)
#define MARGIN 2
//鼠标按下事件
/*
*作用:
*1.判断是否时左键点击 _isleftpressed
*2.获取光标在屏幕中的位置 _plast
*3.左键按下时光标所在区域 _curpos
*/
void RailwayPowerInterface::mousePressEvent(QMouseEvent *event)
{
Q_UNUSED(event);
if (event->button() == Qt::LeftButton)
{
this->_isleftpressed = true;
QPoint temp = event->globalPos();
_plast = temp;
_curpos = countFlag(event->pos(), countRow(event->pos()));
}
}
//鼠标释放事件
/*
*作用:
*1.将_isleftpressed 设为false
*2.将光标样式恢复原样式 setCursor(Qt::ArrowCursor);
*/
void RailwayPowerInterface::mouseReleaseEvent(QMouseEvent *event)
{
Q_UNUSED(event);
if (_isleftpressed)
_isleftpressed = false;
setCursor(Qt::ArrowCursor);
}
//鼠标移动事件
void RailwayPowerInterface::mouseMoveEvent(QMouseEvent *event)
{
Q_UNUSED(event);
if(this->isFullScreen()) return; //窗口铺满全屏,直接返回,不做任何操作
int poss = countFlag(event->pos(), countRow(event->pos()));
setCursorType(poss);
if (_isleftpressed)//是否左击
{
QPoint ptemp = event->globalPos();
ptemp = ptemp - _plast;
if (_curpos == 22)//移动窗口
{
ptemp = ptemp + pos();
move(ptemp);
}
else
{
QRect wid = geometry();
switch (_curpos)//改变窗口的大小
{
case 11:wid.setTopLeft(wid.topLeft() + ptemp); break;//左上角
case 13:wid.setTopRight(wid.topRight() + ptemp); break;//右上角
case 31:wid.setBottomLeft(wid.bottomLeft() + ptemp); break;//左下角
case 33:wid.setBottomRight(wid.bottomRight() + ptemp); break;//右下角
case 12:wid.setTop(wid.top() + ptemp.y()); break;//中上角
case 21:wid.setLeft(wid.left() + ptemp.x()); break;//中左角
case 23:wid.setRight(wid.right() + ptemp.x()); break;//中右角
case 32:wid.setBottom(wid.bottom() + ptemp.y()); break;//中下角
}
setGeometry(wid);
}
_plast = event->globalPos();//更新位置
}
}
//获取光标在窗口所在区域的 列 返回行列坐标
int RailwayPowerInterface::countFlag(QPoint p,int row)//计算鼠标在哪一列和哪一行
{
if(p.y()<MARGIN)
return 10+row;
else if(p.y()>this->height()-MARGIN)
return 30+row;
else
return 20+row;
}
//获取光标在窗口所在区域的 行 返回行数
int RailwayPowerInterface::countRow(QPoint p)
{
return (p.x()<MARGIN) ? 1 : (p.x()>(this->width() - MARGIN) ? 3 : 2);
}
//根据鼠标所在位置改变鼠标指针形状
void RailwayPowerInterface::setCursorType(int flag)
{
switch(flag)
{
case 11:
case 33:
setCursor(Qt::SizeFDiagCursor);
break;
case 13:
case 31:
setCursor(Qt::SizeBDiagCursor);break;
case 21:
case 23:
setCursor(Qt::SizeHorCursor);break;
case 12:
case 32:
setCursor(Qt::SizeVerCursor);break;
case 22:
setCursor(Qt::ArrowCursor);
QApplication::restoreOverrideCursor();//恢复鼠标指针性状
break;
}
}