当前位置:   article > 正文

Qt实现无边框窗口_qt设置无边框窗口

qt设置无边框窗口

目录

创建无边框窗口

窗口区域的划分

        在头文件加入鼠标事件

        设定枚举,将窗口分为9个区域

 鼠标光标在不同区域的变化

右键关闭窗口

中间区域拖动窗口

鼠标在不同方向对窗口的拉伸


本篇为作者第一次学做无边框窗口的历程

创建无边框窗口

        在构造函数内实现:

  1. //最小宽高
  2. this->setMinimumWidth(500);
  3. this->setMinimumHeight(300);
  4. //消除窗口边框
  5. setWindowFlags(Qt::FramelessWindowHint | Qt::WindowSystemMenuHint);
  6. //设置背景色
  7. this->setStyleSheet("background-color:#303030");
  8. //创建两个按钮
  9. btn1=new QPushButton(this);
  10. btn2=new QPushButton(this);
  11. btn1->setText("确认");
  12. btn2->setText("取消");
  13. btn1->setStyleSheet(R"(QPushButton {
  14. background-color: rgb(64, 64, 64);
  15. color:rgb(200,200,200);
  16. border: 1px solid #707070;
  17. border-radius: 5px;
  18. padding: 5px;
  19. })");
  20. btn2->setStyleSheet(R"(QPushButton {
  21. background-color: rgb(64, 64, 64);
  22. color:rgb(200,200,200);
  23. border: 1px solid #707070;
  24. border-radius: 5px;
  25. padding: 5px;
  26. })");
  27. QHBoxLayout* hor=new QHBoxLayout(this);
  28. hor->setSpacing(0);
  29. hor->setContentsMargins(10,10,10,10);
  30. hor->addWidget(btn1);
  31. hor->addWidget(btn2);
  32. //用于判断鼠标左键是否按下
  33. isleftpressed=false;
  34. //消除窗口边框
  35. setWindowFlags(Qt::FramelessWindowHint | Qt::WindowSystemMenuHint);

        在这里先将基本的窗口呈现出来。


窗口区域的划分

        在头文件加入鼠标事件

  1. void mousePressEvent(QMouseEvent* event);
  2. void mouseMoveEvent(QMouseEvent* event);
  3. void mouseReleaseEvent(QMouseEvent* event);

        设定枚举,将窗口分为9个区域

  1. enum Location {
  2. TOP,
  3. BOTTOM,
  4. LEFT,
  5. RIGHT,
  6. TOP_LEFT,
  7. TOP_RIGHT,
  8. BOTTOM_LEFT,
  9. BOTTOM_RIGHT,
  10. CENTER
  11. };

 鼠标光标在不同区域的变化

        在一个窗口里,(0,0)是窗口的最左上角,往右或者是往下坐标都会变大。

        在这里实现鼠标在窗口的八个方向的变化。

        并放入鼠标移动事件,用于判断鼠标位置(location).

  1. #define padding 10
  2. QRect rect=this->rect();
  3. //将坐标转化为相对于整个屏幕的坐标
  4. QPoint topleft=mapToGlobal(rect.topLeft());
  5. QPoint bottomright=mapToGlobal(rect.bottomRight());
  6. int x=globalpos.x();
  7. int y=globalpos.y();
  8. //鼠标位于左上角
  9. if(x>topleft.x()&&x<topleft.x()+padding&&y>topleft.y()&&y<topleft.y()+padding)
  10. {
  11. location=TOP_LEFT;
  12. //这里鼠标光标变化
  13. this->setCursor(QCursor(Qt::SizeFDiagCursor));
  14. }
  15. //鼠标位于左下角
  16. else if(x>topleft.x()&&x<topleft.x()+padding&&y<bottomright.y()&&y>bottomright.y()-padding)
  17. {
  18. location=BOTTOM_LEFT;
  19. this->setCursor(QCursor(Qt::SizeBDiagCursor));
  20. }
  21. //鼠标位于右上角
  22. else if(x<bottomright.x()&&x>bottomright.x()-padding&&y>topleft.y()&&y<topleft.y()+padding)
  23. {
  24. location=TOP_RIGHT;
  25. this->setCursor(QCursor(Qt::SizeBDiagCursor));
  26. }
  27. //鼠标位于右下角
  28. else if(x<bottomright.x()&&x>bottomright.x()-padding&&y>bottomright.y()-padding&&y<bottomright.y())
  29. {
  30. location=BOTTOM_RIGHT;
  31. this->setCursor(Qt::SizeFDiagCursor);
  32. }
  33. //鼠标位于上面
  34. else if(y>topleft.y()&&y<topleft.y()+padding)
  35. {
  36. location=TOP;
  37. this->setCursor(Qt::SizeVerCursor);
  38. }
  39. //鼠标位于左边
  40. else if(x>topleft.x()&&x<topleft.x()+padding)
  41. {
  42. location=LEFT;
  43. this->setCursor(Qt::SizeHorCursor);
  44. }
  45. //鼠标位于下面
  46. else if(y>bottomright.y()-padding&&y<bottomright.y())
  47. {
  48. location=BOTTOM;
  49. this->setCursor(Qt::SizeVerCursor);
  50. }
  51. //鼠标位于右边
  52. else if(x<bottomright.x()&&x>bottomright.x()-padding)
  53. {
  54. location=RIGHT;
  55. this->setCursor(Qt::SizeHorCursor);
  56. }
  57. //鼠标位于中间
  58. else
  59. {
  60. location=CENTER;
  61. this->setCursor(QCursor(Qt::ArrowCursor));
  62. }

将其封装成函数,加入鼠标移动事件。 


 

右键关闭窗口

        窗口边框消除后,右上角的叉叉也随之消失,于是我们加入一个右键关闭窗口的功能。

        先前已经在头文件中加入了三个鼠标事件,现在来实现其中的按下事件

  1. void Widget::mousePressEvent(QMouseEvent* event)
  2. {
  3. switch (event->button())
  4. {
  5. //右键关闭窗口
  6. case Qt::RightButton:
  7. this->close();
  8. break;
  9. default:
  10. break;
  11. }
  12. }

中间区域拖动窗口

        在这里,需要记录鼠标的实时位置,并将窗口实时移动。

        所以我们需要实时触发鼠标移动事件,并启用鼠标追踪。

this->setMouseTracking(true);

        接下来实现修正鼠标按下和移动事件

  1. void Widget::mousePressEvent(QMouseEvent* event)
  2. {
  3. switch (event->button())
  4. {
  5. //右键关闭窗口
  6. case Qt::RightButton:
  7. this->close();
  8. break;
  9. //记录鼠标按下时位置与窗口左上角的距离
  10. case Qt::LeftButton:
  11. //用于判断左键是否按下
  12. isleftpressed=true;
  13. if(location==CENTER)
  14. mousepos=event->globalPos()-this->frameGeometry().topLeft();
  15. default:
  16. break;
  17. }
  18. }

窗口要移动到的新位置即是原窗口位置加上鼠标移动的位置。

鼠标移动时,实时触发。

  1. void Widget::mouseMoveEvent(QMouseEvent *event)
  2. {
  3. //这里是之前鼠标光标变化的函数
  4. if(!isleftpressed)
  5. {
  6. this->setcursorshape(globalpos);
  7. return;
  8. }
  9. //中间位置拖动窗口
  10. if(location==CENTER&&isleftpressed)
  11. {
  12. move(event->globalPos()-mousepos);
  13. event->accept();
  14. return;
  15. }
  16. }

 

鼠标在不同方向对窗口的拉伸

        在这里实现鼠标在边缘八个方向按下拉动时,窗口的变形。

        即鼠标左键按下,触发鼠标移动事件时触发。

  1. void Widget::mouseMoveEvent(QMouseEvent *event)
  2. {
  3. //记录鼠标当前位置
  4. QPoint globalpos=event->globalPos();
  5. QRect rect=this->rect();
  6. QPoint topleft=mapToGlobal(rect.topLeft());
  7. QPoint bottomright=mapToGlobal(rect.bottomRight());
  8. //创建一个矩形,并拉伸,最后设置其为窗口
  9. QRect rmove(topleft,bottomright);
  10. switch (location)
  11. {
  12. case TOP:
  13. //这里的if防止最小后窗口整体向下移动
  14. if(bottomright.y()-globalpos.y()>this->minimumHeight())
  15. rmove.setY(globalpos.y());
  16. break;
  17. case BOTTOM:
  18. rmove.setHeight(globalpos.y()-topleft.y());
  19. break;
  20. case LEFT:
  21. if(bottomright.x()-globalpos.x()>this->minimumWidth())
  22. rmove.setX(globalpos.x());
  23. break;
  24. case RIGHT:
  25. rmove.setWidth(globalpos.x()-topleft.x());
  26. break;
  27. case TOP_LEFT:
  28. if(bottomright.y()-globalpos.y()>this->minimumHeight()&&bottomright.x()-globalpos.x()>this->width())
  29. {
  30. rmove.setY(globalpos.y());
  31. rmove.setX(globalpos.x());
  32. }
  33. break;
  34. case TOP_RIGHT:
  35. if(bottomright.y()-globalpos.y()>this->minimumHeight())
  36. {
  37. rmove.setY(globalpos.y());
  38. rmove.setWidth(globalpos.x()-topleft.x());
  39. }
  40. break;
  41. case BOTTOM_LEFT:
  42. if(bottomright.x()-globalpos.x()>this->width())
  43. {
  44. rmove.setHeight(globalpos.y()-topleft.y());
  45. rmove.setX(globalpos.x());
  46. }
  47. break;
  48. case BOTTOM_RIGHT:
  49. rmove.setHeight(globalpos.y()-topleft.y());
  50. rmove.setWidth(globalpos.x()-topleft.x());
  51. break;
  52. case CENTER:
  53. break;
  54. }
  55. //重新设置窗口几何形状
  56. this->setGeometry(rmove);
  57. return;
  58. }

        需要注意的是在拖动顶部时,只需更新窗口的 Y 坐标,以实现向下拖动的效果。在拖动底部时,更新窗口的高度,以实现向上或向下调整大小的效果。这两种情况之所以有不同的处理方式,是因为拖动顶部只需要改变 Y 坐标,而拖动底部则需要改变高度。同样的逻辑也适用于左、右、左上、右上、左下、右下等不同的边界位置,因为每个位置的操作影响的窗口属性是不同的。

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

闽ICP备14008679号