赞
踩
在使用QT创建窗体的时候,为了使窗口美化,通常不使用QT自带的边框。会调用下面函数去除窗体边框。
setWindowFlags(Qt::FramelessWindowHint)
但是有个问题,当去除了QT自带边框后,窗体就变得不能移动了,也不能改变窗口大小了。这确实是个问题,该怎么去解决呢?
首先我们来解决窗口移动的问题:解决思路就是在鼠标按下事件中记录按下的位置QPoint pLast, 并标记鼠标状态m_bPressed = true; 为按下状态。
- void MainWindow::mousePressEvent(QMouseEvent *event)
- {
- this->setFocus();
- if(Qt::LeftButton == event->button() && 0 == (Qt::WindowMaximized & this->windowState()))
- {
- QPoint temp=event->globalPos();
- pLast=temp; //记录鼠标按下的位置
- event->ignore();
- }
- m_bPressed = true; //标记鼠标为按下状态
- }
然后在鼠标移动事件中进行窗体移动
- void MainWindow::mouseMoveEvent(QMouseEvent * event)
- {
- if(this->isMaximized()) //如果当前是最大化,则不允许移动
- return;
-
- if((event->buttons() & Qt::LeftButton) && m_bPressed)//是否左击
- {
- QPoint ptemp=event->globalPos(); //当前鼠标全局位置
- ptemp=ptemp-pLast; //计算移动变量
- ptemp=ptemp+pos(); //窗口原始位置(pos()) + 鼠标移动变量(ptemp) = 最终窗口位置
- move(ptemp); //移动窗口到新的位置
- }
- }
最后需要在鼠标松开事件中进行状态复位
- void MainWindow::mouseReleaseEvent(QMouseEvent * event)
- {
- QApplication::restoreOverrideCursor();//恢复鼠标指针性状
- event->ignore();
-
- m_bPressed = false;
- }
到这里,就已经全部解决了无边框窗口可以动的问题。但是,但是我们窗口拉伸缩放,进行调节窗口大小的问题还没有解决,这里该怎么解决呢?首先我们将窗口的区域进行划分,如下图
这里我们将一个窗口划分为9个区域,分别为
左上角(1,1)、中上(1,2)、右上角(1,3)
左中 (2,1)、 中间(2,2)、右中 (2,3)
左下角(3,1)、中下(3,2)、 右下角(3,3)
思路应该是这样:
1.当鼠标移动时候,我们首先判断这个光标处于哪个区域
2.当鼠标移动到不同区域,鼠标的形状是不同变化的。
3.根据(2,2)之外的区域,计算初鼠标移动的偏移量,来重新设置窗口的坐标。
比如,鼠标进入区域(2,2)的时候,说明是移动窗口的操作,而不是进行窗口缩放的操作。除了区域(2,2)之外,其他8个区域均是进行窗口缩放的,但是处于不同区域内,鼠标的形状是不一样。
看代码
- void MainWindow::mouseMoveEvent(QMouseEvent * event)
- {
- if(this->isMaximized()) //如果最大化,则不允许移动和拉伸
- return;
-
- int poss=countFlag(event->pos(),countRow(event->pos()));//计算出来鼠标在哪个区域
-
- if(!event->buttons())
- setCursorType(poss);//根据不同的区域设置不同的鼠标形状
-
- if((event->buttons() & Qt::LeftButton) && m_bPressed)//是否左击
- {
- QPoint ptemp=event->globalPos();
- ptemp=ptemp-pLast; //鼠标移动的偏移量
- if(m_curPos==22) //区域(2,2)表示移动窗口
- {
- ptemp=ptemp+pos();
- move(ptemp);
- }
- else
- {
- QRect wid=geometry();
-
- int minWidth = this->minimumWidth();
- int minHeight = this->minimumHeight();
-
- switch(m_curPos)//改变窗口的大小
- {
- case 11:
- {
- 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 13:
- {
- 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 31:
- {
- 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 33:
- {
- 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 12:
- {
- int topY = wid.top();
- if(wid.height() > minHeight || ptemp.y() < 0)
- topY = topY + ptemp.y();
-
- wid.setTop(topY);
- break;//中上角
- }
- case 21:
- {
- int leftX = wid.left();
-
- if(wid.width() > minWidth || ptemp.x() < 0)
- leftX = leftX + ptemp.x();
-
- wid.setLeft(leftX);
- break;//中左角
- }
- case 23:
- {
- int rightX = wid.right();
-
- if(wid.width() > minWidth || ptemp.x() > 0)
- rightX = rightX + ptemp.x();
-
- wid.setRight(rightX);
- break;//中右角
- }
- case 32:
- {
- int botY = wid.bottom();
- if(wid.height() > minHeight || ptemp.y() > 0)
- botY = botY + ptemp.y();
-
- wid.setBottom(botY);
- break;//中下角
- }
- }
- setGeometry(wid); //设置窗口的位置
- }
- pLast=event->globalPos();//更新位置
- }
- event->ignore();
-
- }
计算鼠标在哪个区域
- int MainWindow::countFlag(QPoint p,int row)//计算鼠标在哪一列和哪一行
- {
- if(p.y()<MARGIN)
- return 10+row;
- else if(p.y()>this->height()-MARGIN)
- return 30+row;
- else
- return 20+row;
- }
根据鼠标所在位置改变鼠标形状
- void MainWindow::setCursorType(int flag)//根据鼠标所在位置改变鼠标指针形状
- {
- Qt::CursorShape cursor;
- switch(flag)
- {
- case 11:
- case 33:
- cursor=Qt::SizeFDiagCursor;break;
- case 13:
- case 31:
- cursor=Qt::SizeBDiagCursor;break;
- case 21:
- case 23:
- cursor=Qt::SizeHorCursor;break;
- case 12:
- case 32:
- cursor=Qt::SizeVerCursor;break;
- case 22:
- cursor=Qt::ArrowCursor;break;
- default:
- // QApplication::restoreOverrideCursor();//恢复鼠标指针性状
- break;
-
- }
- setCursor(cursor);
- }
到这里,就可以正常的进行窗口拉伸进行窗口缩放了。
截止现在,已经完成了一个可拉伸,可移动的无边框窗口。
这里还有个隐患,就是设置了无边框窗口之后,里面的内容就不会及时刷新了
setWindowFlags(Qt::FramelessWindowHint)
我们应该怎么做呢?需要重写显示事件
- void MainWindow::showEvent(QShowEvent* event)
- {
- this->setAttribute(Qt::WA_Mapped);//解决不能及时刷新的bug
- QMainWindow::showEvent(event);
- }
这里就完美的解决了所有的问题。
我这里做了一个demo,https://download.csdn.net/download/xiezhongyuan07/10390321
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。