有時爲了美觀,會自己製作邊框, 這就意味着,你完成上述功能,要實現三個功能:
<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