有时为了美观,会自己制作边框, 这就意味着,你完成上述功能,要实现三个功能:
<1>窗体可自由 伸缩. 可大可小.
<2>窗体可随着鼠标移动
<3>自己实现标题栏(包含 最小化,最大化,关闭)
那么就按照上述的顺序来讲解:
窗体可自由 伸缩. 可大可小:
1:有时你会发现,当鼠标放在边框边时 鼠标会有变化,(箭头向上,向下, 向左,向右, 左上.... )
思路:
计算出这9个区域的 Rect ,然后根据鼠标停放的 pos 在哪个位置, 来设置鼠标的形状
鼠标 设置 可查看 文档 QCursor,
代码如下:
enum LocaTion{top,bottom,left,right,left_top,left_bottm,right_top,right_botm,middle};
LocaTion site_flag;
void Widget::set_Cursor(QMouseEvent *event)
{
int width = this->width();
int height = this->height();
QRect top_ = QRect(pading, 0, width - pading * 2, pading);
QRect bottom_ = QRect(pading, height - pading, width - pading * 2,pading);
QRect left_ = QRect(0, pading, pading, height - pading * 2);
QRect right_ = QRect(width - pading, pading, pading,height - pading * 2);
QRect top_left = QRect(0, 0, pading, pading);
QRect top_right = QRect(width - pading, 0, pading, pading);
QRect bottom_left = QRect(0, height - pading, pading, pading);
QRect bottom_right = QRect(width - pading, height - pading, pading, pading);
if(top_.contains(event->pos()))
{
this->setCursor(QCursor(Qt::SizeVerCursor)); // 设置鼠标形状 上
site_flag = top;
}
else if(bottom_.contains(event->pos()))
{
this->setCursor(QCursor(Qt::SizeVerCursor)); // 设置鼠标形状 下
site_flag = bottom;
}
else if(left_.contains(event->pos()))
{
this->setCursor(QCursor(Qt::SizeHorCursor)); // 设置鼠标形状 左
site_flag = left;
}
else if(right_.contains(event->pos()))
{
this->setCursor(QCursor(Qt::SizeHorCursor)); // 设置鼠标形状 右
site_flag = right;
}
else if (top_left.contains(event->pos()))
{
this->setCursor(QCursor(Qt::SizeFDiagCursor)); // 设置鼠标形状 左上
site_flag = left_top;
}
else if (top_right.contains(event->pos()))
{
this->setCursor(QCursor(Qt::SizeBDiagCursor)); // 设置鼠标形状 右上
site_flag = right_top;
}
else if (bottom_left.contains(event->pos()))
{
this->setCursor(QCursor(Qt::SizeBDiagCursor)); // 设置鼠标形状 左下
site_flag = left_bottm;
}
else if(bottom_right.contains(event->pos()))
{
this->setCursor(QCursor(Qt::SizeFDiagCursor)); // 设置鼠标形状 右下
site_flag = right_botm;
}
else
{
this->setCursor(QCursor(Qt::ArrowCursor));
site_flag = middle;
}
}
2:当鼠标发生变化时 进行,拖动
思路:
窗体有他的最小 height ,width , 当伸缩时 相对距离大于 他的最小 height 和 width 才允发生变化
注意;
窗体的原点在左上角. 通过x() , y() 就可以获取,;通过 setx() ,sety()设置他的左上的的位置
void Widget::set_Stretch(QMouseEvent *event)
{
QRect rect = this->rect();
QPoint gloPoint = event->globalPos() ;
QPoint topLeft = mapToGlobal(rect.topLeft());
QPoint bottomRight = mapToGlobal(rect.bottomRight());
QPoint bottomLeft = mapToGlobal(rect.bottomLeft());
QPoint topRight = mapToGlobal(rect.topRight());
// 窗体的的最初大小
QRect rMove(topLeft, bottomRight);
switch (site_flag) {
case left:
/*右边框 x 座标减去 左边正在延伸的 x 座标 大于最小宽度的情况下,*/
if (bottomRight.x() - gloPoint.x() > this->minimumWidth())
{
/*
因为窗体的原点在左上角, 你拖动的正好是 左边,有一个相同点 那就是左边,所以设置 setx() 就可以. 和setwidth() 没有关系的.
*/
rMove.setX(gloPoint.x());
}
this->setGeometry(rMove);
break;
case top:
if (bottomRight.y() - gloPoint.y() > this->minimumHeight())
{
/*共同点: 上 设置 sety()*/
rMove.setY(gloPoint.y());
}
this->setGeometry(rMove);
break;
case right:
if (gloPoint.x() - bottomLeft.x() > this->minimumWidth())
{
/*和左上没有共同点,这个时候,就不能通过setx() 来设置了, 可以仔细想想. 原点不变, 延伸右边,可以设置他的宽度啊*/
rMove.setWidth(gloPoint.x() - bottomLeft.x());
}
this->setGeometry(rMove);
break;
case bottom:
if (gloPoint.y() - topRight.y() > this->minimumHeight())
{
//和右边的思路一样
rMove.setHeight(gloPoint.y() - topRight.y());
}
this->setGeometry(rMove);
break;
case left_top:
// 和上面的判断有点不一样,这快判断的是 相对距离小于 最小size
//将左上 分为左边,上边两部分
if ((bottomRight.y() - gloPoint.y() <= this->minimumHeight()) )
{
// 当窗体缩小的时候, 高度小于窗体最小高度, 有可能这会的宽度还是大于最小width , 所以就有如下判断
rMove.setX(topLeft.x());
rMove.setHeight(this->height()); //你也可以 改成 this->minnumheight()
}
else if( (bottomRight.x() - gloPoint.x() <= this->minimumWidth()))
{
rMove.setWidth(this->minimumWidth());
rMove.setY(gloPoint.y());
}
else
{
// 左上就是原点, 所以设置就可以通过 setx sety
rMove.setX(gloPoint.x());
rMove.setY(gloPoint.y());
}
this->setGeometry(rMove);
break;
case right_top:
if (bottomRight.y() - gloPoint.y() <= this->minimumHeight())
{
rMove.setWidth(gloPoint.x() - topLeft.x());
rMove.setY(topRight.y());
}
else if(( gloPoint.x() - bottomLeft.x() <= this->minimumWidth()))
{
rMove.setWidth(this->minimumWidth());
rMove.setY(gloPoint.y());
}
else
{
//和原点左上的 共同点, 上边,那么就可以用sety(),而右边 通过 setWidth
rMove.setWidth(gloPoint.x() - topLeft.x());
rMove.setY(gloPoint.y());
}
this->setGeometry(rMove);
break;
case left_bottm:
if(bottomRight.x() - gloPoint.x() <= this->minimumWidth())
{
rMove.setWidth(this->minimumWidth());
rMove.setHeight(gloPoint.y() - topLeft.y());
}
else if(gloPoint.y() - topLeft.y() <= this->minimumHeight())
{
rMove.setX(gloPoint.x());
rMove.setHeight(this->minimumHeight());
}
else
{
rMove.setBottomLeft(gloPoint);
}
this->setGeometry(rMove);
break;
case right_botm:
if( gloPoint.y() - topLeft.y() <= this->minimumHeight())
{
rMove.setWidth(gloPoint.x()- topLeft.x());
rMove.setHeight(this->minimumHeight());
}
else if(( gloPoint.x() - bottomLeft.x() <= this->minimumWidth()))
{
rMove.setWidth(this->minimumWidth());
rMove.setHeight(gloPoint.y()- topLeft.y());
}
else
{
rMove.setWidth(gloPoint.x()- topLeft.x());
rMove.setHeight(gloPoint.y()- topLeft.y());
}
this->setGeometry(rMove);
break;
case middle:
//当鼠标停放在中间的时候, 那么这个操作就是拖动.
window()->move(window()->pos() + gloPoint - Current_Pos);
Current_Pos = gloPoint;
default:
event->ignore();
break;
}
HB->setContentsMargins(0,0,0,this->height()-30);
}
窗体可随着鼠标移动, 自己实现标题栏(包含 最小化,最大化,关闭)
上面的其实已经有了:
当鼠标停放在 middle 的区域,就是拖动了.
具体可看,标题栏制作,的博客,里面有讲解
https://blog.csdn.net/sinat_14854721/article/details/80243813