Qt实现无边框窗口的示例代码
作者:小宇宙Zz
本文主要介绍了Qt实现无边框窗口的示例代码,主要包括鼠标光标在不同区域的变化,关闭拖动窗口,窗口支持任意拉伸等,具有一定的参考价值,感兴趣的可以了解一下
创建无边框窗口
在构造函数内实现:
//最小宽高 this->setMinimumWidth(500); this->setMinimumHeight(300); //消除窗口边框 setWindowFlags(Qt::FramelessWindowHint | Qt::WindowSystemMenuHint); //设置背景色 this->setStyleSheet("background-color:#303030"); //创建两个按钮 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);
在这里先将基本的窗口呈现出来。
窗口区域的划分
在头文件加入鼠标事件
void mousePressEvent(QMouseEvent* event); void mouseMoveEvent(QMouseEvent* event); void mouseReleaseEvent(QMouseEvent* event);
设定枚举,将窗口分为9个区域
enum Location { TOP, BOTTOM, LEFT, RIGHT, TOP_LEFT, TOP_RIGHT, BOTTOM_LEFT, BOTTOM_RIGHT, CENTER };
鼠标光标在不同区域的变化
在一个窗口里,(0,0)是窗口的最左上角,往右或者是往下坐标都会变大。
在这里实现鼠标在窗口的八个方向的变化。
并放入鼠标移动事件,用于判断鼠标位置(location).
#define padding 10 QRect rect=this->rect(); //将坐标转化为相对于整个屏幕的坐标 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)); }
将其封装成函数,加入鼠标移动事件。
右键关闭窗口
窗口边框消除后,右上角的叉叉也随之消失,于是我们加入一个右键关闭窗口的功能。
先前已经在头文件中加入了三个鼠标事件,现在来实现其中的按下事件
void Widget::mousePressEvent(QMouseEvent* event) { switch (event->button()) { //右键关闭窗口 case Qt::RightButton: this->close(); break; default: break; } }
中间区域拖动窗口
在这里,需要记录鼠标的实时位置,并将窗口实时移动。
所以我们需要实时触发鼠标移动事件,并启用鼠标追踪。
this->setMouseTracking(true);
接下来实现修正鼠标按下和移动事件
void Widget::mousePressEvent(QMouseEvent* event) { switch (event->button()) { //右键关闭窗口 case Qt::RightButton: this->close(); break; //记录鼠标按下时位置与窗口左上角的距离 case Qt::LeftButton: //用于判断左键是否按下 isleftpressed=true; if(location==CENTER) mousepos=event->globalPos()-this->frameGeometry().topLeft(); default: break; } }
窗口要移动到的新位置即是原窗口位置加上鼠标移动的位置。
鼠标移动时,实时触发。
void Widget::mouseMoveEvent(QMouseEvent *event) { //这里是之前鼠标光标变化的函数 if(!isleftpressed) { this->setcursorshape(globalpos); return; } //中间位置拖动窗口 if(location==CENTER&&isleftpressed) { move(event->globalPos()-mousepos); event->accept(); return; } }
鼠标在不同方向对窗口的拉伸
在这里实现鼠标在边缘八个方向按下拉动时,窗口的变形。
即鼠标左键按下,触发鼠标移动事件时触发。
void Widget::mouseMoveEvent(QMouseEvent *event) { //记录鼠标当前位置 QPoint globalpos=event->globalPos(); QRect rect=this->rect(); QPoint topleft=mapToGlobal(rect.topLeft()); QPoint bottomright=mapToGlobal(rect.bottomRight()); //创建一个矩形,并拉伸,最后设置其为窗口 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 坐标,以实现向下拖动的效果。在拖动底部时,更新窗口的高度,以实现向上或向下调整大小的效果。这两种情况之所以有不同的处理方式,是因为拖动顶部只需要改变 Y 坐标,而拖动底部则需要改变高度。同样的逻辑也适用于左、右、左上、右上、左下、右下等不同的边界位置,因为每个位置的操作影响的窗口属性是不同的。
到此这篇关于Qt实现无边框窗口的示例代码的文章就介绍到这了,更多相关Qt 无边框窗口内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!