当前位置:   article > 正文

QT 创建一个 可移动、可拉伸的无边框窗体_qt 无边框窗口拉伸

qt 无边框窗口拉伸

    在使用QT创建窗体的时候,为了使窗口美化,通常不使用QT自带的边框。会调用下面函数去除窗体边框。

setWindowFlags(Qt::FramelessWindowHint)

    但是有个问题,当去除了QT自带边框后,窗体就变得不能移动了,也不能改变窗口大小了。这确实是个问题,该怎么去解决呢?

    首先我们来解决窗口移动的问题:解决思路就是在鼠标按下事件中记录按下的位置QPoint pLast, 并标记鼠标状态m_bPressed  = true; 为按下状态。

  1. void MainWindow::mousePressEvent(QMouseEvent *event)
  2. {
  3. this->setFocus();
  4. if(Qt::LeftButton == event->button() && 0 == (Qt::WindowMaximized & this->windowState()))
  5. {
  6. QPoint temp=event->globalPos();
  7. pLast=temp;    //记录鼠标按下的位置
  8. event->ignore();
  9. }
  10. m_bPressed = true; //标记鼠标为按下状态
  11. }

    然后在鼠标移动事件中进行窗体移动

  1. void MainWindow::mouseMoveEvent(QMouseEvent * event)
  2. {
  3. if(this->isMaximized()) //如果当前是最大化,则不允许移动
  4. return;
  5. if((event->buttons() & Qt::LeftButton) && m_bPressed)//是否左击
  6. {
  7. QPoint ptemp=event->globalPos();          //当前鼠标全局位置      
  8. ptemp=ptemp-pLast;                        //计算移动变量
  9. ptemp=ptemp+pos();                        //窗口原始位置(pos()) + 鼠标移动变量(ptemp) = 最终窗口位置
  10. move(ptemp);                              //移动窗口到新的位置
  11. }
  12. }

最后需要在鼠标松开事件中进行状态复位

  1. void MainWindow::mouseReleaseEvent(QMouseEvent * event)
  2. {
  3. QApplication::restoreOverrideCursor();//恢复鼠标指针性状
  4. event->ignore();
  5. m_bPressed = false;
  6. }

到这里,就已经全部解决了无边框窗口可以动的问题。但是,但是我们窗口拉伸缩放,进行调节窗口大小的问题还没有解决,这里该怎么解决呢?首先我们将窗口的区域进行划分,如下图

这里我们将一个窗口划分为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个区域均是进行窗口缩放的,但是处于不同区域内,鼠标的形状是不一样。

    看代码

  1. void MainWindow::mouseMoveEvent(QMouseEvent * event)
  2. {
  3. if(this->isMaximized()) //如果最大化,则不允许移动和拉伸
  4. return;
  5. int poss=countFlag(event->pos(),countRow(event->pos()));//计算出来鼠标在哪个区域
  6. if(!event->buttons())
  7. setCursorType(poss);//根据不同的区域设置不同的鼠标形状
  8. if((event->buttons() & Qt::LeftButton) && m_bPressed)//是否左击
  9. {
  10. QPoint ptemp=event->globalPos();
  11. ptemp=ptemp-pLast; //鼠标移动的偏移量
  12. if(m_curPos==22) //区域(2,2)表示移动窗口
  13. {
  14. ptemp=ptemp+pos();
  15. move(ptemp);
  16. }
  17. else
  18. {
  19. QRect wid=geometry();
  20. int minWidth = this->minimumWidth();
  21. int minHeight = this->minimumHeight();
  22. switch(m_curPos)//改变窗口的大小
  23. {
  24. case 11:
  25. {
  26. QPoint pos = wid.topLeft();
  27. if(wid.width() > minWidth || ptemp.x() < 0)
  28. pos.rx() = pos.rx() + ptemp.x();
  29. if(wid.height() > minHeight || ptemp.y() < 0)
  30. pos.ry() = pos.ry() + ptemp.y();
  31. wid.setTopLeft(pos);
  32. break;//左上角
  33. }
  34. case 13:
  35. {
  36. QPoint pos = wid.topRight();
  37. if(wid.width() > minWidth || ptemp.x() > 0)
  38. pos.rx() = pos.rx() + ptemp.x();
  39. if(wid.height() > minHeight || ptemp.y() < 0)
  40. pos.ry() = pos.ry() + ptemp.y();
  41. wid.setTopRight(pos);
  42. break;//右上角
  43. }
  44. case 31:
  45. {
  46. QPoint pos = wid.bottomLeft();
  47. if(wid.width() > minWidth || ptemp.x() < 0)
  48. pos.rx() = pos.rx() + ptemp.x();
  49. if(wid.height() > minHeight || ptemp.y() > 0)
  50. pos.ry() = pos.ry() + ptemp.y();
  51. wid.setBottomLeft(pos);
  52. break;//左下角
  53. }
  54. case 33:
  55. {
  56. QPoint pos = wid.bottomRight();
  57. if(wid.width() > minWidth || ptemp.x() > 0)
  58. pos.rx() = pos.rx() + ptemp.x();
  59. if(wid.height() > minHeight || ptemp.y() > 0)
  60. pos.ry() = pos.ry() + ptemp.y();
  61. wid.setBottomRight(pos);
  62. break;//右下角
  63. }
  64. case 12:
  65. {
  66. int topY = wid.top();
  67. if(wid.height() > minHeight || ptemp.y() < 0)
  68. topY = topY + ptemp.y();
  69. wid.setTop(topY);
  70. break;//中上角
  71. }
  72. case 21:
  73. {
  74. int leftX = wid.left();
  75. if(wid.width() > minWidth || ptemp.x() < 0)
  76. leftX = leftX + ptemp.x();
  77. wid.setLeft(leftX);
  78. break;//中左角
  79. }
  80. case 23:
  81. {
  82. int rightX = wid.right();
  83. if(wid.width() > minWidth || ptemp.x() > 0)
  84. rightX = rightX + ptemp.x();
  85. wid.setRight(rightX);
  86. break;//中右角
  87. }
  88. case 32:
  89. {
  90. int botY = wid.bottom();
  91. if(wid.height() > minHeight || ptemp.y() > 0)
  92. botY = botY + ptemp.y();
  93. wid.setBottom(botY);
  94. break;//中下角
  95. }
  96. }
  97. setGeometry(wid); //设置窗口的位置
  98. }
  99. pLast=event->globalPos();//更新位置
  100. }
  101. event->ignore();
  102. }

计算鼠标在哪个区域

  1. int MainWindow::countFlag(QPoint p,int row)//计算鼠标在哪一列和哪一行
  2. {
  3. if(p.y()<MARGIN)
  4. return 10+row;
  5. else if(p.y()>this->height()-MARGIN)
  6. return 30+row;
  7. else
  8. return 20+row;
  9. }

根据鼠标所在位置改变鼠标形状

  1. void MainWindow::setCursorType(int flag)//根据鼠标所在位置改变鼠标指针形状
  2. {
  3. Qt::CursorShape cursor;
  4. switch(flag)
  5. {
  6. case 11:
  7. case 33:
  8. cursor=Qt::SizeFDiagCursor;break;
  9. case 13:
  10. case 31:
  11. cursor=Qt::SizeBDiagCursor;break;
  12. case 21:
  13. case 23:
  14. cursor=Qt::SizeHorCursor;break;
  15. case 12:
  16. case 32:
  17. cursor=Qt::SizeVerCursor;break;
  18. case 22:
  19. cursor=Qt::ArrowCursor;break;
  20. default:
  21. // QApplication::restoreOverrideCursor();//恢复鼠标指针性状
  22. break;
  23. }
  24. setCursor(cursor);
  25. }

到这里,就可以正常的进行窗口拉伸进行窗口缩放了。

截止现在,已经完成了一个可拉伸,可移动的无边框窗口。

 

这里还有个隐患,就是设置了无边框窗口之后,里面的内容就不会及时刷新了

setWindowFlags(Qt::FramelessWindowHint)

我们应该怎么做呢?需要重写显示事件

  1. void MainWindow::showEvent(QShowEvent* event)
  2. {
  3. this->setAttribute(Qt::WA_Mapped);//解决不能及时刷新的bug
  4. QMainWindow::showEvent(event);
  5. }

 

这里就完美的解决了所有的问题。

 

 

我这里做了一个demo,https://download.csdn.net/download/xiezhongyuan07/10390321

没有积分的小伙伴,评论留下你的邮箱,看到后第一时间发送源码

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/94964
推荐阅读
相关标签
  

闽ICP备14008679号