Qt實現(xiàn)無邊框窗口的示例代碼
創(chuàng)建無邊框窗口
在構(gòu)造函數(shù)內(nèi)實現(xiàn):
//最小寬高 this->setMinimumWidth(500); this->setMinimumHeight(300); //消除窗口邊框 setWindowFlags(Qt::FramelessWindowHint | Qt::WindowSystemMenuHint); //設置背景色 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); //用于判斷鼠標左鍵是否按下 isleftpressed=false; //消除窗口邊框 setWindowFlags(Qt::FramelessWindowHint | Qt::WindowSystemMenuHint);
在這里先將基本的窗口呈現(xiàn)出來。
窗口區(qū)域的劃分
在頭文件加入鼠標事件
void mousePressEvent(QMouseEvent* event); void mouseMoveEvent(QMouseEvent* event); void mouseReleaseEvent(QMouseEvent* event);
設定枚舉,將窗口分為9個區(qū)域
enum Location { TOP, BOTTOM, LEFT, RIGHT, TOP_LEFT, TOP_RIGHT, BOTTOM_LEFT, BOTTOM_RIGHT, CENTER };
鼠標光標在不同區(qū)域的變化
在一個窗口里,(0,0)是窗口的最左上角,往右或者是往下坐標都會變大。
在這里實現(xiàn)鼠標在窗口的八個方向的變化。
并放入鼠標移動事件,用于判斷鼠標位置(location).
#define padding 10 QRect rect=this->rect(); //將坐標轉(zhuǎn)化為相對于整個屏幕的坐標 QPoint topleft=mapToGlobal(rect.topLeft()); QPoint bottomright=mapToGlobal(rect.bottomRight()); int x=globalpos.x(); int y=globalpos.y(); //鼠標位于左上角 if(x>topleft.x()&&x<topleft.x()+padding&&y>topleft.y()&&y<topleft.y()+padding) { location=TOP_LEFT; //這里鼠標光標變化 this->setCursor(QCursor(Qt::SizeFDiagCursor)); } //鼠標位于左下角 else if(x>topleft.x()&&x<topleft.x()+padding&&y<bottomright.y()&&y>bottomright.y()-padding) { location=BOTTOM_LEFT; this->setCursor(QCursor(Qt::SizeBDiagCursor)); } //鼠標位于右上角 else if(x<bottomright.x()&&x>bottomright.x()-padding&&y>topleft.y()&&y<topleft.y()+padding) { location=TOP_RIGHT; this->setCursor(QCursor(Qt::SizeBDiagCursor)); } //鼠標位于右下角 else if(x<bottomright.x()&&x>bottomright.x()-padding&&y>bottomright.y()-padding&&y<bottomright.y()) { location=BOTTOM_RIGHT; this->setCursor(Qt::SizeFDiagCursor); } //鼠標位于上面 else if(y>topleft.y()&&y<topleft.y()+padding) { location=TOP; this->setCursor(Qt::SizeVerCursor); } //鼠標位于左邊 else if(x>topleft.x()&&x<topleft.x()+padding) { location=LEFT; this->setCursor(Qt::SizeHorCursor); } //鼠標位于下面 else if(y>bottomright.y()-padding&&y<bottomright.y()) { location=BOTTOM; this->setCursor(Qt::SizeVerCursor); } //鼠標位于右邊 else if(x<bottomright.x()&&x>bottomright.x()-padding) { location=RIGHT; this->setCursor(Qt::SizeHorCursor); } //鼠標位于中間 else { location=CENTER; this->setCursor(QCursor(Qt::ArrowCursor)); }
將其封裝成函數(shù),加入鼠標移動事件。
右鍵關(guān)閉窗口
窗口邊框消除后,右上角的叉叉也隨之消失,于是我們加入一個右鍵關(guān)閉窗口的功能。
先前已經(jīng)在頭文件中加入了三個鼠標事件,現(xiàn)在來實現(xiàn)其中的按下事件
void Widget::mousePressEvent(QMouseEvent* event) { switch (event->button()) { //右鍵關(guān)閉窗口 case Qt::RightButton: this->close(); break; default: break; } }
中間區(qū)域拖動窗口
在這里,需要記錄鼠標的實時位置,并將窗口實時移動。
所以我們需要實時觸發(fā)鼠標移動事件,并啟用鼠標追蹤。
this->setMouseTracking(true);
接下來實現(xiàn)修正鼠標按下和移動事件
void Widget::mousePressEvent(QMouseEvent* event) { switch (event->button()) { //右鍵關(guān)閉窗口 case Qt::RightButton: this->close(); break; //記錄鼠標按下時位置與窗口左上角的距離 case Qt::LeftButton: //用于判斷左鍵是否按下 isleftpressed=true; if(location==CENTER) mousepos=event->globalPos()-this->frameGeometry().topLeft(); default: break; } }
窗口要移動到的新位置即是原窗口位置加上鼠標移動的位置。
鼠標移動時,實時觸發(fā)。
void Widget::mouseMoveEvent(QMouseEvent *event) { //這里是之前鼠標光標變化的函數(shù) if(!isleftpressed) { this->setcursorshape(globalpos); return; } //中間位置拖動窗口 if(location==CENTER&&isleftpressed) { move(event->globalPos()-mousepos); event->accept(); return; } }
鼠標在不同方向?qū)Υ翱诘睦?/h2>
在這里實現(xiàn)鼠標在邊緣八個方向按下拉動時,窗口的變形。
即鼠標左鍵按下,觸發(fā)鼠標移動事件時觸發(fā)。
void Widget::mouseMoveEvent(QMouseEvent *event)
{
//記錄鼠標當前位置
QPoint globalpos=event->globalPos();
QRect rect=this->rect();
QPoint topleft=mapToGlobal(rect.topLeft());
QPoint bottomright=mapToGlobal(rect.bottomRight());
//創(chuàng)建一個矩形,并拉伸,最后設置其為窗口
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;
}
//重新設置窗口幾何形狀
this->setGeometry(rmove);
return;
}
在這里實現(xiàn)鼠標在邊緣八個方向按下拉動時,窗口的變形。
即鼠標左鍵按下,觸發(fā)鼠標移動事件時觸發(fā)。
void Widget::mouseMoveEvent(QMouseEvent *event) { //記錄鼠標當前位置 QPoint globalpos=event->globalPos(); QRect rect=this->rect(); QPoint topleft=mapToGlobal(rect.topLeft()); QPoint bottomright=mapToGlobal(rect.bottomRight()); //創(chuàng)建一個矩形,并拉伸,最后設置其為窗口 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; } //重新設置窗口幾何形狀 this->setGeometry(rmove); return; }
需要注意的是在拖動頂部時,只需更新窗口的 Y 坐標,以實現(xiàn)向下拖動的效果。在拖動底部時,更新窗口的高度,以實現(xiàn)向上或向下調(diào)整大小的效果。這兩種情況之所以有不同的處理方式,是因為拖動頂部只需要改變 Y 坐標,而拖動底部則需要改變高度。同樣的邏輯也適用于左、右、左上、右上、左下、右下等不同的邊界位置,因為每個位置的操作影響的窗口屬性是不同的。
到此這篇關(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