无标题栏窗口的实现拖动,和边的拉伸功能
本文的功能實現,參考了鏈接:https://blog.csdn.net/Ternence_God/article/details/100150377,圖片也是來自其。
引言
創建的程序采用系統窗口,直接可以進行拖動,向八個方向拉伸,一旦設置窗口無標題欄,即:setWindowFlags(Qt::FramelessWindowHint);后,窗口的拖動,拉伸功能便需要重新實現。
效果
由于暫時還沒有向平臺上傳視頻,所以咱沒有插入視頻來直觀的顯示程序運行的效果。后期補上。
實現
開發環境
下面以一個小的demo來實現窗口的拖動和拉伸功能。
思路
窗口的拖動
鼠標按下后記住當前鼠標按下點的位置,這個點相對于屏幕而言,同時獲取窗口左上角的位置,當鼠標按下移動后,獲取當前移動到的點的位置,也是相對于桌面而言的坐標,用移動后的位置減去剛開始鼠標按下的點得到偏移量,用鼠標左上角的點加上偏移量便是移動后窗口的位置,調用move()函數將窗口移動到指定點,實現窗口在鼠標按下不放可拖動。這里不用考慮偏移量是加上還是減去,因為記錄了鼠標剛開始按下的點之后,向右移,偏移量變為正值,向左移偏移量便為負值。
窗口的拉伸
由于我們獲取窗口的上下左右四個邊以及四個角的坐標來判斷當鼠標進入指定邊或者角時,兩者的坐標并不相同,而是有一定的偏差,這是采用劃分區域來實現鼠標進入窗口置頂的邊或角,從而按照不同的邊、角置頂鼠標的樣式,保存原來窗口的位置大小,記錄鼠標變樣后按下點的坐標,和鼠標移動后點的坐標,求得偏移量,從而計算各個邊角的位置,從新設置窗口的位置大小。且需要記錄窗口被拉伸后鼠標的位置,防止下一次操作直接從上一次拉伸后不釋放坐標直接拉伸。
區域劃分
項目結構
基類選擇QDialog類,其它都是默認,然后創建項目。
具體代碼
.pro,.ui文件采用自動生成的,不做任何改變。
widget.h
widget.cpp
#include "widget.h" #include "ui_widget.h" #include <QMouseEvent> #include <QDebug>Widget::Widget(QWidget *parent): QWidget(parent),m_floatValue(10), ui(new Ui::Widget) {ui->setupUi(this);setWindowFlags(Qt::FramelessWindowHint);setMouseTracking(true); }Widget::~Widget() {delete ui; }void Widget::mousePressEvent(QMouseEvent *event) {if (event->button() == Qt::LeftButton) { // m_pressPos = event->globalPos();//獲取在屏幕坐標系統中的位置 // m_topLeftPos = geometry().topLeft();//獲取窗口左上角的位置,原本采取左上角坐標+偏移量m_lastPos = event->globalPos();m_pressPos = pos();m_region = determineArea(event->pos());//在父窗口中的位置// qDebug()<<QStringLiteral("鼠標位置:")<<m_pressPos<<QStringLiteral("位置:")<<event->pos() // <<QStringLiteral("窗口左上角的位置:")<<m_topLeftPos;//在父窗口中的位置}QWidget::mousePressEvent(event); }void Widget::mouseMoveEvent(QMouseEvent *event) {if (isMaximized()){return;}setMouseCursorStyle(event);if (event->buttons() == Qt::LeftButton) {QPoint offset = event->globalPos() - m_lastPos;if (m_region == midArea) {move(m_pressPos + offset);}else {mouseStrechDrag(event,offset);}}QWidget::mouseMoveEvent(event); }void Widget::mouseReleaseEvent(QMouseEvent *event) {QWidget::mouseReleaseEvent(event); }void Widget::setMouseCursorStyle(QMouseEvent *event) {int region = determineArea(event->pos());//這里的區域必須為局部變量,否則會出現拉伸中出現區域變更,導致功能紊亂switch (region) {case topLeftCorner:case rightBottomConrner:setCursor(Qt::SizeFDiagCursor);//設置光標的形狀使用setCursor(),使用setShape()設置不上,并不知為啥break;case topBorder:case bottomBorder:setCursor(Qt::SizeVerCursor);break;case topRightCorner:case leftBottomConrner:setCursor(Qt::SizeBDiagCursor);break;case leftBorder:case rightBorder:setCursor(Qt::SizeHorCursor);break;case midArea:setCursor(Qt::ArrowCursor);break;default:break;} }int Widget::determineArea(QPoint pos) {int xArea = 0;int yArea = 0;int areaFlag = 0;if (pos.x() < m_floatValue) {xArea = oneArea;}else if (pos.x() > width() - m_floatValue) {xArea = threeArea;}else {xArea = twoArea;}if (pos.y() < m_floatValue) {yArea = oneArea;}else if (pos.y() > height() - m_floatValue) {yArea = threeArea;}else {yArea = twoArea;}return areaFlag = yArea * 10 + xArea; }void Widget::mouseStrechDrag(QMouseEvent *event,QPoint &offset) {QRect rect = geometry();qDebug()<<QStringLiteral("鼠標移動的位置:")<<event->globalPos()<<QStringLiteral("按下點位置:")<<m_pressPos<<QStringLiteral("偏移量:")<<event->globalPos()-m_pressPos;switch (m_region) {case topLeftCorner:rect.setTopLeft(rect.topLeft() + offset);break;case rightBottomConrner:rect.setBottomRight(rect.bottomRight() + offset);break;case topBorder:rect.setTop(rect.top() + offset.y());break;case bottomBorder:rect.setBottom(rect.bottom() + offset.y());break;case topRightCorner:rect.setTopRight(rect.topRight() + offset);break;case leftBottomConrner:rect.setBottomLeft(rect.bottomLeft() + offset);break;case leftBorder:rect.setLeft(rect.left() + offset.x());break;case rightBorder:rect.setRight(rect.right() + offset.x());break;default:break;}//設置拉伸的最小寬度和高度if (rect.width() < 200 || rect.height() < 100) {return ;}setGeometry(rect);m_lastPos = event->globalPos(); }//void Widget::setMouseCursorStyle(QMouseEvent *event) //{ // //轉換后存在誤差,鼠標在左下角獲取的位置與左下角的位置不一樣,因而無法實現下述方法 // qDebug()<<QStringLiteral("鼠標在父窗口的位置:")<<mapFromParent(event->globalPos())<< // QStringLiteral("鼠標的位置:")<<event->pos()<<QStringLiteral("左上角")<<geometry().topLeft() // <<QStringLiteral("右上角")<<geometry().topRight()<<QStringLiteral("左下角")<<geometry().bottomLeft() // <<QStringLiteral("右下角")<<geometry().bottomRight()<<QStringLiteral("左邊")<<geometry().left() // <<QStringLiteral("右邊")<<geometry().right()<<QStringLiteral("上邊")<<geometry().top() // <<QStringLiteral("下邊")<<geometry().bottom()<<QStringLiteral("轉換后左下角")<<mapFromParent(geometry().bottomLeft());//獲取位置相同,都是鼠標在父窗口中的位置 // if (event->pos().x() > geometry().left() &&event->pos().x() < geometry().right() // && event->pos().y() > geometry().top() && event->pos().y() < geometry().bottom()) // {//中間 // cursor().setShape(Qt::ArrowCursor); // }else if (event->pos() == mapFromParent(geometry().topLeft())) {//左上角 // qDebug()<<QStringLiteral("鼠標在左上角"); // cursor().setShape(Qt::SizeFDiagCursor); // }else if (event->pos() == mapFromParent(geometry().topRight())) {//右上角 // cursor().setShape(Qt::SizeBDiagCursor); // }else if (event->pos() == geometry().bottomLeft()) {//左下角 // cursor().setShape(Qt::SizeBDiagCursor); // }else if (event->pos() == geometry().bottomRight()) {//右下角 // cursor().setShape(Qt::SizeFDiagCursor); // }else if (event->pos().x() == geometry().left()) {//左邊 // cursor().setShape(Qt::SizeHorCursor); // }else if (event->pos().x() == geometry().right()) {//右邊 // cursor().setShape(Qt::SizeHorCursor); // }else if (event->pos().y() == geometry().top()) {//上邊 // cursor().setShape(Qt::SizeVerCursor); // }else if (event->pos().y() == geometry().bottom()) {//下邊 // cursor().setShape(Qt::SizeVerCursor); // } //}main.cpp文件也采用默認生成的文件。
這樣就可以編譯,運行,查看程序的運行效果了。
注意點
總結
以上是生活随笔為你收集整理的无标题栏窗口的实现拖动,和边的拉伸功能的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 初始化成员列表
- 下一篇: python目前有多少库文件_必学Pyt