Qt實現(xiàn)無邊框窗口的示例代碼
創(chuàng)建無邊框窗口
在構(gòu)造函數(shù)內(nèi)實現(xiàn):
//最小寬高
this->setMinimumWidth(500);
this->setMinimumHeight(300);
//消除窗口邊框
setWindowFlags(Qt::FramelessWindowHint | Qt::WindowSystemMenuHint);
//設(shè)置背景色
this->setStyleSheet("background-color:#303030");
//創(chuàng)建兩個按鈕
btn1=new QPushButton(this);
btn2=new QPushButton(this);
btn1->setText("確認");
btn2->setText("取消");
btn1->setStyleSheet(R"(QPushButton {
background-color: rgb(64, 64, 64);
color:rgb(200,200,200);
border: 1px solid #707070;
border-radius: 5px;
padding: 5px;
})");
btn2->setStyleSheet(R"(QPushButton {
background-color: rgb(64, 64, 64);
color:rgb(200,200,200);
border: 1px solid #707070;
border-radius: 5px;
padding: 5px;
})");
QHBoxLayout* hor=new QHBoxLayout(this);
hor->setSpacing(0);
hor->setContentsMargins(10,10,10,10);
hor->addWidget(btn1);
hor->addWidget(btn2);
//用于判斷鼠標(biāo)左鍵是否按下
isleftpressed=false;
//消除窗口邊框
setWindowFlags(Qt::FramelessWindowHint | Qt::WindowSystemMenuHint);在這里先將基本的窗口呈現(xiàn)出來。

窗口區(qū)域的劃分
在頭文件加入鼠標(biāo)事件
void mousePressEvent(QMouseEvent* event); void mouseMoveEvent(QMouseEvent* event); void mouseReleaseEvent(QMouseEvent* event);
設(shè)定枚舉,將窗口分為9個區(qū)域
enum Location {
TOP,
BOTTOM,
LEFT,
RIGHT,
TOP_LEFT,
TOP_RIGHT,
BOTTOM_LEFT,
BOTTOM_RIGHT,
CENTER
};鼠標(biāo)光標(biāo)在不同區(qū)域的變化
在一個窗口里,(0,0)是窗口的最左上角,往右或者是往下坐標(biāo)都會變大。
在這里實現(xiàn)鼠標(biāo)在窗口的八個方向的變化。
并放入鼠標(biāo)移動事件,用于判斷鼠標(biāo)位置(location).
#define padding 10
QRect rect=this->rect();
//將坐標(biāo)轉(zhuǎn)化為相對于整個屏幕的坐標(biāo)
QPoint topleft=mapToGlobal(rect.topLeft());
QPoint bottomright=mapToGlobal(rect.bottomRight());
int x=globalpos.x();
int y=globalpos.y();
//鼠標(biāo)位于左上角
if(x>topleft.x()&&x<topleft.x()+padding&&y>topleft.y()&&y<topleft.y()+padding)
{
location=TOP_LEFT;
//這里鼠標(biāo)光標(biāo)變化
this->setCursor(QCursor(Qt::SizeFDiagCursor));
}
//鼠標(biāo)位于左下角
else if(x>topleft.x()&&x<topleft.x()+padding&&y<bottomright.y()&&y>bottomright.y()-padding)
{
location=BOTTOM_LEFT;
this->setCursor(QCursor(Qt::SizeBDiagCursor));
}
//鼠標(biāo)位于右上角
else if(x<bottomright.x()&&x>bottomright.x()-padding&&y>topleft.y()&&y<topleft.y()+padding)
{
location=TOP_RIGHT;
this->setCursor(QCursor(Qt::SizeBDiagCursor));
}
//鼠標(biāo)位于右下角
else if(x<bottomright.x()&&x>bottomright.x()-padding&&y>bottomright.y()-padding&&y<bottomright.y())
{
location=BOTTOM_RIGHT;
this->setCursor(Qt::SizeFDiagCursor);
}
//鼠標(biāo)位于上面
else if(y>topleft.y()&&y<topleft.y()+padding)
{
location=TOP;
this->setCursor(Qt::SizeVerCursor);
}
//鼠標(biāo)位于左邊
else if(x>topleft.x()&&x<topleft.x()+padding)
{
location=LEFT;
this->setCursor(Qt::SizeHorCursor);
}
//鼠標(biāo)位于下面
else if(y>bottomright.y()-padding&&y<bottomright.y())
{
location=BOTTOM;
this->setCursor(Qt::SizeVerCursor);
}
//鼠標(biāo)位于右邊
else if(x<bottomright.x()&&x>bottomright.x()-padding)
{
location=RIGHT;
this->setCursor(Qt::SizeHorCursor);
}
//鼠標(biāo)位于中間
else
{
location=CENTER;
this->setCursor(QCursor(Qt::ArrowCursor));
}將其封裝成函數(shù),加入鼠標(biāo)移動事件。
右鍵關(guān)閉窗口
窗口邊框消除后,右上角的叉叉也隨之消失,于是我們加入一個右鍵關(guān)閉窗口的功能。
先前已經(jīng)在頭文件中加入了三個鼠標(biāo)事件,現(xiàn)在來實現(xiàn)其中的按下事件
void Widget::mousePressEvent(QMouseEvent* event)
{
switch (event->button())
{
//右鍵關(guān)閉窗口
case Qt::RightButton:
this->close();
break;
default:
break;
}
}中間區(qū)域拖動窗口
在這里,需要記錄鼠標(biāo)的實時位置,并將窗口實時移動。
所以我們需要實時觸發(fā)鼠標(biāo)移動事件,并啟用鼠標(biāo)追蹤。
this->setMouseTracking(true);
接下來實現(xiàn)修正鼠標(biāo)按下和移動事件
void Widget::mousePressEvent(QMouseEvent* event)
{
switch (event->button())
{
//右鍵關(guān)閉窗口
case Qt::RightButton:
this->close();
break;
//記錄鼠標(biāo)按下時位置與窗口左上角的距離
case Qt::LeftButton:
//用于判斷左鍵是否按下
isleftpressed=true;
if(location==CENTER)
mousepos=event->globalPos()-this->frameGeometry().topLeft();
default:
break;
}
}窗口要移動到的新位置即是原窗口位置加上鼠標(biāo)移動的位置。
鼠標(biāo)移動時,實時觸發(fā)。
void Widget::mouseMoveEvent(QMouseEvent *event)
{
//這里是之前鼠標(biāo)光標(biāo)變化的函數(shù)
if(!isleftpressed)
{
this->setcursorshape(globalpos);
return;
}
//中間位置拖動窗口
if(location==CENTER&&isleftpressed)
{
move(event->globalPos()-mousepos);
event->accept();
return;
}
}鼠標(biāo)在不同方向?qū)Υ翱诘睦?/h2>
在這里實現(xiàn)鼠標(biāo)在邊緣八個方向按下拉動時,窗口的變形。
即鼠標(biāo)左鍵按下,觸發(fā)鼠標(biāo)移動事件時觸發(fā)。
void Widget::mouseMoveEvent(QMouseEvent *event)
{
//記錄鼠標(biāo)當(dāng)前位置
QPoint globalpos=event->globalPos();
QRect rect=this->rect();
QPoint topleft=mapToGlobal(rect.topLeft());
QPoint bottomright=mapToGlobal(rect.bottomRight());
//創(chuàng)建一個矩形,并拉伸,最后設(shè)置其為窗口
QRect rmove(topleft,bottomright);
switch (location)
{
case TOP:
//這里的if防止最小后窗口整體向下移動
if(bottomright.y()-globalpos.y()>this->minimumHeight())
rmove.setY(globalpos.y());
break;
case BOTTOM:
rmove.setHeight(globalpos.y()-topleft.y());
break;
case LEFT:
if(bottomright.x()-globalpos.x()>this->minimumWidth())
rmove.setX(globalpos.x());
break;
case RIGHT:
rmove.setWidth(globalpos.x()-topleft.x());
break;
case TOP_LEFT:
if(bottomright.y()-globalpos.y()>this->minimumHeight()&&bottomright.x()-globalpos.x()>this->width())
{
rmove.setY(globalpos.y());
rmove.setX(globalpos.x());
}
break;
case TOP_RIGHT:
if(bottomright.y()-globalpos.y()>this->minimumHeight())
{
rmove.setY(globalpos.y());
rmove.setWidth(globalpos.x()-topleft.x());
}
break;
case BOTTOM_LEFT:
if(bottomright.x()-globalpos.x()>this->width())
{
rmove.setHeight(globalpos.y()-topleft.y());
rmove.setX(globalpos.x());
}
break;
case BOTTOM_RIGHT:
rmove.setHeight(globalpos.y()-topleft.y());
rmove.setWidth(globalpos.x()-topleft.x());
break;
case CENTER:
break;
}
//重新設(shè)置窗口幾何形狀
this->setGeometry(rmove);
return;
}
在這里實現(xiàn)鼠標(biāo)在邊緣八個方向按下拉動時,窗口的變形。
即鼠標(biāo)左鍵按下,觸發(fā)鼠標(biāo)移動事件時觸發(fā)。
void Widget::mouseMoveEvent(QMouseEvent *event)
{
//記錄鼠標(biāo)當(dāng)前位置
QPoint globalpos=event->globalPos();
QRect rect=this->rect();
QPoint topleft=mapToGlobal(rect.topLeft());
QPoint bottomright=mapToGlobal(rect.bottomRight());
//創(chuàng)建一個矩形,并拉伸,最后設(shè)置其為窗口
QRect rmove(topleft,bottomright);
switch (location)
{
case TOP:
//這里的if防止最小后窗口整體向下移動
if(bottomright.y()-globalpos.y()>this->minimumHeight())
rmove.setY(globalpos.y());
break;
case BOTTOM:
rmove.setHeight(globalpos.y()-topleft.y());
break;
case LEFT:
if(bottomright.x()-globalpos.x()>this->minimumWidth())
rmove.setX(globalpos.x());
break;
case RIGHT:
rmove.setWidth(globalpos.x()-topleft.x());
break;
case TOP_LEFT:
if(bottomright.y()-globalpos.y()>this->minimumHeight()&&bottomright.x()-globalpos.x()>this->width())
{
rmove.setY(globalpos.y());
rmove.setX(globalpos.x());
}
break;
case TOP_RIGHT:
if(bottomright.y()-globalpos.y()>this->minimumHeight())
{
rmove.setY(globalpos.y());
rmove.setWidth(globalpos.x()-topleft.x());
}
break;
case BOTTOM_LEFT:
if(bottomright.x()-globalpos.x()>this->width())
{
rmove.setHeight(globalpos.y()-topleft.y());
rmove.setX(globalpos.x());
}
break;
case BOTTOM_RIGHT:
rmove.setHeight(globalpos.y()-topleft.y());
rmove.setWidth(globalpos.x()-topleft.x());
break;
case CENTER:
break;
}
//重新設(shè)置窗口幾何形狀
this->setGeometry(rmove);
return;
}需要注意的是在拖動頂部時,只需更新窗口的 Y 坐標(biāo),以實現(xiàn)向下拖動的效果。在拖動底部時,更新窗口的高度,以實現(xiàn)向上或向下調(diào)整大小的效果。這兩種情況之所以有不同的處理方式,是因為拖動頂部只需要改變 Y 坐標(biāo),而拖動底部則需要改變高度。同樣的邏輯也適用于左、右、左上、右上、左下、右下等不同的邊界位置,因為每個位置的操作影響的窗口屬性是不同的。
到此這篇關(guān)于Qt實現(xiàn)無邊框窗口的示例代碼的文章就介紹到這了,更多相關(guān)Qt 無邊框窗口內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Qt GUI圖形圖像開發(fā)之Qt表格控件QTableView簡單使用方法及QTableView與QTableWidget區(qū)
這篇文章主要介紹了Qt GUI圖形圖像開發(fā)之Qt表格控件QTableView簡單使用方法,需要的朋友可以參考下2020-03-03
FFRPC應(yīng)用 Client/Server使用及原理解析
這篇文章主要介紹了FFRPC應(yīng)用 Client/Server使用及原理解析,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2019-08-08

