源码文末已给出
// 去掉标题栏,去掉工具栏,窗口置顶
setWindowFlags(Qt::FramelessWindowHint | Qt::Tool | Qt::WindowStaysOnTopHint);
this->setWindowOpacity(0.7);
隐藏标题栏后窗体是无法拖动的,这个时候就需要重写mousePressEvent、mouseMoveEvent和mouseReleaseEvent。在对应的mainwindow.h头文件中添加一个成员变量QPoint。同时重定义三个鼠标事件函数
设置窗口无标题
this->setWindowFlags(Qt::FramelessWindowHint | Qt::WindowMinimizeButtonHint);
//在头文件中重写鼠标事件
private slots:
//由于去掉显示界面的菜单栏和标题栏,无法拖动窗口,重写关于窗口拖动用的几个函数
void mousePressEvent(QMouseEvent *e);
void mouseMoveEvent(QMouseEvent *e);
void mouseReleaseEvent(QMouseEvent *e);
private:
QPoint last;//窗口拖动用变量
重写mousePressEvent、mouseMoveEvent和mouseReleaseEvent函数。在cpp中
//三个鼠标事件的重写
//鼠标释放
void pre_canshuwidget::mousePressEvent(QMouseEvent *e)
{
if(e->button()== Qt::LeftButton) //鼠标左键释放
last = e->globalPos();
}
//鼠标移动
void pre_canshuwidget::mouseMoveEvent(QMouseEvent *e)
{
if(e->buttons()==Qt::LeftButton) //坐标左键按下并移动
{
int dx = e->globalX() - last.x();
int dy = e->globalY() - last.y();
last = e->globalPos();
move(x()+dx, y()+dy);
}
}
//鼠标按下
void pre_canshuwidget::mouseReleaseEvent(QMouseEvent *e)
{
if(e->button()==Qt::LeftButton) //鼠标左键按下
{
int dx = e->globalX() - last.x();
int dy = e->globalY() - last.y();
move(x()+dx, y()+dy);
}
}
参考:https://blog.csdn.net/qq_27085429/article/details/90735485
2020.6.30更新
经过上面的处理,我们已经能够实现将窗口标题隐藏后可以拖动窗口,但还不是一个完美的无边框窗口,不能改变窗口大小,不能拖拽还原。
要实现上面的功能,我们要继续改造重写鼠标事件。首先在头文件中定义一个枚举,来判别鼠标当前所在的位置,改变鼠标形状。
先看效果
Mainwindow.h
public:
enum MousePoss{LeftUp=0,Up,RightUp,Right,RightDown,Down,LeftDown,Left,Middle};
private:
MainWindow::MousePoss mp_curPos; //记录鼠标当前所在区域的变量
思路:
//计算鼠标位置
MainWindow::MousePoss MainWindow::calcmouseposs(QPoint p)
{
MainWindow::MousePoss mp;
if(p.x()<MOUSE_MARGIN && p.y() < MOUSE_MARGIN)
mp=MainWindow::MousePoss::LeftUp; //左上
else if(p.x()>MOUSE_MARGIN && p.y()< MOUSE_MARGIN && p.x()<this->width()-MOUSE_MARGIN)
mp = MainWindow::MousePoss::Up; //上
else if(p.x() > this->width()-MOUSE_MARGIN && p.y() < MOUSE_MARGIN)
mp = MainWindow::MousePoss::RightUp; //右上
else if(p.x() > this->width()-MOUSE_MARGIN && p.y() > MOUSE_MARGIN && p.y()<this->height()-MOUSE_MARGIN)
mp = MainWindow::MousePoss::Right; //右
else if(p.x() > this->width()-MOUSE_MARGIN && p.y() > this->height()-MOUSE_MARGIN)
mp = MainWindow::MousePoss::RightDown; //右下
else if(p.x()>MOUSE_MARGIN && p.x() < this->width()-MOUSE_MARGIN && p.y() > this->height()-MOUSE_MARGIN)
mp = MainWindow::MousePoss::Down; //下
else if(p.x() < MOUSE_MARGIN && p.y() > this->height()-MOUSE_MARGIN)
mp = MainWindow::MousePoss::LeftDown; //左下
else if(p.x() < MOUSE_MARGIN && p.y() < this->height()-MOUSE_MARGIN && p.y()>MOUSE_MARGIN)
mp = MainWindow::MousePoss::Left; //左
else
mp=MainWindow::MousePoss::Middle; //中间
return mp;
}
//修改鼠标样式
void MainWindow::setCursorType(MainWindow::MousePoss type)
{
Qt::CursorShape cursor;
switch(type)
{
case MainWindow::MousePoss::LeftUp:
case MainWindow::MousePoss::RightDown:
cursor=Qt::SizeFDiagCursor;
break;
case MainWindow::MousePoss::Up:
case MainWindow::MousePoss::Down:
cursor=Qt::SizeVerCursor;
break;
case MainWindow::MousePoss::RightUp:
case MainWindow::MousePoss::LeftDown:
cursor=Qt::SizeBDiagCursor;
break;
case MainWindow::MousePoss::Right:
case MainWindow::MousePoss::Left:
cursor=Qt::SizeHorCursor;
break;
default:
cursor=Qt::ArrowCursor;
break;
}
setCursor(cursor);
}
//改变窗口的大小
void MainWindow::changeWindowSize(MainWindow::MousePoss type, QRect &wid,QPoint ptemp,int minWidth, int minHeight)
{
switch(type)//改变窗口的大小
{
case MainWindow::MousePoss::LeftUp:
{
QPoint pos = wid.topLeft();
if(wid.width() > minWidth || ptemp.x() < 0)
pos.rx() = pos.rx() + ptemp.x();
if(wid.height() > minHeight || ptemp.y() < 0)
pos.ry() = pos.ry() + ptemp.y();
wid.setTopLeft(pos);
break;//左上角
}
case MainWindow::MousePoss::RightUp:
{
QPoint pos = wid.topRight();
if(wid.width() > minWidth || ptemp.x() > 0)
pos.rx() = pos.rx() + ptemp.x();
if(wid.height() > minHeight || ptemp.y() < 0)
pos.ry() = pos.ry() + ptemp.y();
wid.setTopRight(pos);
break;//右上角
}
case MainWindow::MousePoss::LeftDown:
{
QPoint pos = wid.bottomLeft();
if(wid.width() > minWidth || ptemp.x() < 0)
pos.rx() = pos.rx() + ptemp.x();
if(wid.height() > minHeight || ptemp.y() > 0)
pos.ry() = pos.ry() + ptemp.y();
wid.setBottomLeft(pos);
break;//左下角
}
case MainWindow::MousePoss::RightDown:
{
QPoint pos = wid.bottomRight();
if(wid.width() > minWidth || ptemp.x() > 0)
pos.rx() = pos.rx() + ptemp.x();
if(wid.height() > minHeight || ptemp.y() > 0)
pos.ry() = pos.ry() + ptemp.y();
wid.setBottomRight(pos);
break;//右下角
}
case MainWindow::MousePoss::Up:
{
int topY = wid.top();
if(wid.height() > minHeight || ptemp.y() < 0)
topY = topY + ptemp.y();
wid.setTop(topY);
break;//上
}
case MainWindow::MousePoss::Left:
{
int leftX = wid.left();
if(wid.width() > minWidth || ptemp.x() < 0)
leftX = leftX + ptemp.x();
wid.setLeft(leftX);
break;//左
}
case MainWindow::MousePoss::Right:
{
int rightX = wid.right();
if(wid.width() > minWidth || ptemp.x() > 0)
rightX = rightX + ptemp.x();
wid.setRight(rightX);
break;//右
}
case MainWindow::MousePoss::Down:
{
int botY = wid.bottom();
if(wid.height() > minHeight || ptemp.y() > 0)
botY = botY + ptemp.y();
wid.setBottom(botY);
break;//下
}
default:
break;
}
}
//三个鼠标事件的重写
void MainWindow::mousePressEvent(QMouseEvent *e)
{
if(e->button()== Qt::LeftButton) //鼠标左键按下
{
last = e->globalPos();
e->ignore();
}
}
//鼠标移动
void MainWindow::mouseMoveEvent(QMouseEvent *e)
{
//最大化状态,鼠标是否在标题栏,拖拽还原
if(this->isMaximized())
{
if(ui->fram_title->geometry().contains(this->mapFromGlobal(QCursor::pos())) && e->buttons()==Qt::LeftButton)
{
QPoint ptemp=e->globalPos();
if(ptemp!=last)
{
this->showNormal();
}
}
}
MainWindow::MousePoss curPos=calcmouseposs(e->pos());
if(!e->buttons())
{
setCursorType(curPos);
mp_curPos=curPos;
}
if(e->buttons()==Qt::LeftButton) //坐标左键按下并移动
{
QPoint ptemp=e->globalPos();
ptemp=ptemp-last; //鼠标移动的偏移量
if(mp_curPos==MainWindow::MousePoss::Middle && ui->fram_title->geometry().contains(this->mapFromGlobal(QCursor::pos())))
{
move(ptemp+pos());
}
else
{
QRect wid=geometry();
int minWidth = this->minimumWidth();
int minHeight = this->minimumHeight();
changeWindowSize(mp_curPos,wid,ptemp,minWidth,minHeight);
//更新大小
setGeometry(wid);
}
last = e->globalPos();
}
e->ignore();
}
//鼠标释放
void MainWindow::mouseReleaseEvent(QMouseEvent *e)
{
if(e->button()==Qt::LeftButton && ui->fram_title->geometry().contains(this->mapFromGlobal(QCursor::pos()))) //鼠标左键释放
{
int dx = e->globalX() - last.x();
int dy = e->globalY() - last.y();
move(x()+dx, y()+dy);
}
QApplication::restoreOverrideCursor();//恢复鼠标指针性状
e->ignore();
}
注意注意注意:qt的鼠标事件默认情况是只有当按键按下才会被qt监控,想要不发生按下事件时也接收鼠标信号,我们就需要手动设置部件追踪鼠标。
//追踪鼠标,写在构造函数中
this->setMouseTracking(true);
ui->centralWidget->setMouseTracking(true);
ui->fram_title->setMouseTracking(true);
这里有一个坑,当你设置的鼠标追踪事件部件是父部件,而窗口里面有一个子部件占用父部件较大面积时,在子部件中就接收不到鼠标信号了。
再次更新:双击标题栏最大化(还原)
这个也很简单,只需要重写鼠标双击事件就可以达到目的了。
//在头文件中添加
protected:
//窗口双击事件
void mouseDoubleClickEvent(QMouseEvent *e);
实现:
void MainWindow::mouseDoubleClickEvent(QMouseEvent *e)
{
if(ui->fram_title->geometry().contains(this->mapFromGlobal(QCursor::pos())))
{
if(this->isMaximized())
{
this->showNormal();
/*TODO一些其他需要处理的事情*/
}
else
{
this->showMaximized();
/*TODO一些其他需要处理的事情*/
}
}
else
{
QMainWindow::mouseDoubleClickEvent(e);
}
}
源码链接