Qt實(shí)現(xiàn)無(wú)邊框窗口的示例代碼
創(chuàng)建無(wú)邊框窗口
在構(gòu)造函數(shù)內(nèi)實(shí)現(xiàn):
//最小寬高 this->setMinimumWidth(500); this->setMinimumHeight(300); //消除窗口邊框 setWindowFlags(Qt::FramelessWindowHint | Qt::WindowSystemMenuHint); //設(shè)置背景色 this->setStyleSheet("background-color:#303030"); //創(chuàng)建兩個(gè)按鈕 btn1=new QPushButton(this); btn2=new QPushButton(this); btn1->setText("確認(rèn)"); 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)出來(lái)。
窗口區(qū)域的劃分
在頭文件加入鼠標(biāo)事件
void mousePressEvent(QMouseEvent* event); void mouseMoveEvent(QMouseEvent* event); void mouseReleaseEvent(QMouseEvent* event);
設(shè)定枚舉,將窗口分為9個(gè)區(qū)域
enum Location { TOP, BOTTOM, LEFT, RIGHT, TOP_LEFT, TOP_RIGHT, BOTTOM_LEFT, BOTTOM_RIGHT, CENTER };
鼠標(biāo)光標(biāo)在不同區(qū)域的變化
在一個(gè)窗口里,(0,0)是窗口的最左上角,往右或者是往下坐標(biāo)都會(huì)變大。
在這里實(shí)現(xiàn)鼠標(biāo)在窗口的八個(gè)方向的變化。
并放入鼠標(biāo)移動(dòng)事件,用于判斷鼠標(biāo)位置(location).
#define padding 10 QRect rect=this->rect(); //將坐標(biāo)轉(zhuǎn)化為相對(duì)于整個(gè)屏幕的坐標(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)移動(dòng)事件。
右鍵關(guān)閉窗口
窗口邊框消除后,右上角的叉叉也隨之消失,于是我們加入一個(gè)右鍵關(guān)閉窗口的功能。
先前已經(jīng)在頭文件中加入了三個(gè)鼠標(biāo)事件,現(xiàn)在來(lái)實(shí)現(xiàn)其中的按下事件
void Widget::mousePressEvent(QMouseEvent* event) { switch (event->button()) { //右鍵關(guān)閉窗口 case Qt::RightButton: this->close(); break; default: break; } }
中間區(qū)域拖動(dòng)窗口
在這里,需要記錄鼠標(biāo)的實(shí)時(shí)位置,并將窗口實(shí)時(shí)移動(dòng)。
所以我們需要實(shí)時(shí)觸發(fā)鼠標(biāo)移動(dòng)事件,并啟用鼠標(biāo)追蹤。
this->setMouseTracking(true);
接下來(lái)實(shí)現(xiàn)修正鼠標(biāo)按下和移動(dòng)事件
void Widget::mousePressEvent(QMouseEvent* event) { switch (event->button()) { //右鍵關(guān)閉窗口 case Qt::RightButton: this->close(); break; //記錄鼠標(biāo)按下時(shí)位置與窗口左上角的距離 case Qt::LeftButton: //用于判斷左鍵是否按下 isleftpressed=true; if(location==CENTER) mousepos=event->globalPos()-this->frameGeometry().topLeft(); default: break; } }
窗口要移動(dòng)到的新位置即是原窗口位置加上鼠標(biāo)移動(dòng)的位置。
鼠標(biāo)移動(dòng)時(shí),實(shí)時(shí)觸發(fā)。
void Widget::mouseMoveEvent(QMouseEvent *event) { //這里是之前鼠標(biāo)光標(biāo)變化的函數(shù) if(!isleftpressed) { this->setcursorshape(globalpos); return; } //中間位置拖動(dòng)窗口 if(location==CENTER&&isleftpressed) { move(event->globalPos()-mousepos); event->accept(); return; } }
鼠標(biāo)在不同方向?qū)Υ翱诘睦?/h2>
在這里實(shí)現(xiàn)鼠標(biāo)在邊緣八個(gè)方向按下拉動(dòng)時(shí),窗口的變形。
即鼠標(biāo)左鍵按下,觸發(fā)鼠標(biāo)移動(dòng)事件時(shí)觸發(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)建一個(gè)矩形,并拉伸,最后設(shè)置其為窗口
QRect rmove(topleft,bottomright);
switch (location)
{
case TOP:
//這里的if防止最小后窗口整體向下移動(dòng)
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;
}
在這里實(shí)現(xiàn)鼠標(biāo)在邊緣八個(gè)方向按下拉動(dòng)時(shí),窗口的變形。
即鼠標(biāo)左鍵按下,觸發(fā)鼠標(biāo)移動(dòng)事件時(shí)觸發(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)建一個(gè)矩形,并拉伸,最后設(shè)置其為窗口 QRect rmove(topleft,bottomright); switch (location) { case TOP: //這里的if防止最小后窗口整體向下移動(dòng) 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; }
需要注意的是在拖動(dòng)頂部時(shí),只需更新窗口的 Y 坐標(biāo),以實(shí)現(xiàn)向下拖動(dòng)的效果。在拖動(dòng)底部時(shí),更新窗口的高度,以實(shí)現(xiàn)向上或向下調(diào)整大小的效果。這兩種情況之所以有不同的處理方式,是因?yàn)橥蟿?dòng)頂部只需要改變 Y 坐標(biāo),而拖動(dòng)底部則需要改變高度。同樣的邏輯也適用于左、右、左上、右上、左下、右下等不同的邊界位置,因?yàn)槊總€(gè)位置的操作影響的窗口屬性是不同的。
到此這篇關(guān)于Qt實(shí)現(xiàn)無(wú)邊框窗口的示例代碼的文章就介紹到這了,更多相關(guān)Qt 無(wú)邊框窗口內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Qt GUI圖形圖像開(kāi)發(fā)之Qt表格控件QTableView簡(jiǎn)單使用方法及QTableView與QTableWidget區(qū)
這篇文章主要介紹了Qt GUI圖形圖像開(kāi)發(fā)之Qt表格控件QTableView簡(jiǎn)單使用方法,需要的朋友可以參考下2020-03-03C語(yǔ)言修煉之路靈根孕育源流出?初識(shí)C言大道生上篇
C語(yǔ)言是一門(mén)面向過(guò)程、抽象化的通用程序設(shè)計(jì)語(yǔ)言,廣泛應(yīng)用于底層開(kāi)發(fā)。C語(yǔ)言能以簡(jiǎn)易的方式編譯、處理低級(jí)存儲(chǔ)器。C語(yǔ)言是僅產(chǎn)生少量的機(jī)器語(yǔ)言以及不需要任何運(yùn)行環(huán)境支持便能運(yùn)行的高效率程序設(shè)計(jì)語(yǔ)言2022-03-03C++ 學(xué)習(xí)之旅三 我和超級(jí)瑪麗有個(gè)約會(huì)
學(xué)習(xí)了c++有一周有余了吧,感謝孫鑫老師的視頻教程,讓我 對(duì)C++有了基本的了解,并理解到C++與.net 的許許多多的區(qū)別,更要感謝網(wǎng)民為programaking的人,會(huì)為我提供了超級(jí)瑪麗制作揭秘 這套寶貴的教程,讓我 做做出了這個(gè)項(xiàng)目,對(duì)c++ 有了一個(gè)更深層次的認(rèn)識(shí)2012-11-11FFRPC應(yīng)用 Client/Server使用及原理解析
這篇文章主要介紹了FFRPC應(yīng)用 Client/Server使用及原理解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-08-08