无标题栏窗口的实现拖动,和边的拉伸功能
本文的功能實(shí)現(xiàn),參考了鏈接:https://blog.csdn.net/Ternence_God/article/details/100150377,圖片也是來(lái)自其。
引言
創(chuàng)建的程序采用系統(tǒng)窗口,直接可以進(jìn)行拖動(dòng),向八個(gè)方向拉伸,一旦設(shè)置窗口無(wú)標(biāo)題欄,即:setWindowFlags(Qt::FramelessWindowHint);后,窗口的拖動(dòng),拉伸功能便需要重新實(shí)現(xiàn)。
效果
由于暫時(shí)還沒有向平臺(tái)上傳視頻,所以咱沒有插入視頻來(lái)直觀的顯示程序運(yùn)行的效果。后期補(bǔ)上。
實(shí)現(xiàn)
開發(fā)環(huán)境
下面以一個(gè)小的demo來(lái)實(shí)現(xiàn)窗口的拖動(dòng)和拉伸功能。
思路
窗口的拖動(dòng)
鼠標(biāo)按下后記住當(dāng)前鼠標(biāo)按下點(diǎn)的位置,這個(gè)點(diǎn)相對(duì)于屏幕而言,同時(shí)獲取窗口左上角的位置,當(dāng)鼠標(biāo)按下移動(dòng)后,獲取當(dāng)前移動(dòng)到的點(diǎn)的位置,也是相對(duì)于桌面而言的坐標(biāo),用移動(dòng)后的位置減去剛開始鼠標(biāo)按下的點(diǎn)得到偏移量,用鼠標(biāo)左上角的點(diǎn)加上偏移量便是移動(dòng)后窗口的位置,調(diào)用move()函數(shù)將窗口移動(dòng)到指定點(diǎn),實(shí)現(xiàn)窗口在鼠標(biāo)按下不放可拖動(dòng)。這里不用考慮偏移量是加上還是減去,因?yàn)橛涗浟耸髽?biāo)剛開始按下的點(diǎn)之后,向右移,偏移量變?yōu)檎?#xff0c;向左移偏移量便為負(fù)值。
窗口的拉伸
由于我們獲取窗口的上下左右四個(gè)邊以及四個(gè)角的坐標(biāo)來(lái)判斷當(dāng)鼠標(biāo)進(jìn)入指定邊或者角時(shí),兩者的坐標(biāo)并不相同,而是有一定的偏差,這是采用劃分區(qū)域來(lái)實(shí)現(xiàn)鼠標(biāo)進(jìn)入窗口置頂?shù)倪吇蚪?#xff0c;從而按照不同的邊、角置頂鼠標(biāo)的樣式,保存原來(lái)窗口的位置大小,記錄鼠標(biāo)變樣后按下點(diǎn)的坐標(biāo),和鼠標(biāo)移動(dòng)后點(diǎn)的坐標(biāo),求得偏移量,從而計(jì)算各個(gè)邊角的位置,從新設(shè)置窗口的位置大小。且需要記錄窗口被拉伸后鼠標(biāo)的位置,防止下一次操作直接從上一次拉伸后不釋放坐標(biāo)直接拉伸。
區(qū)域劃分
項(xiàng)目結(jié)構(gòu)
基類選擇QDialog類,其它都是默認(rèn),然后創(chuàng)建項(xiàng)目。
具體代碼
.pro,.ui文件采用自動(dòng)生成的,不做任何改變。
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();//獲取在屏幕坐標(biāo)系統(tǒng)中的位置 // m_topLeftPos = geometry().topLeft();//獲取窗口左上角的位置,原本采取左上角坐標(biāo)+偏移量m_lastPos = event->globalPos();m_pressPos = pos();m_region = determineArea(event->pos());//在父窗口中的位置// qDebug()<<QStringLiteral("鼠標(biāo)位置:")<<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());//這里的區(qū)域必須為局部變量,否則會(huì)出現(xiàn)拉伸中出現(xiàn)區(qū)域變更,導(dǎo)致功能紊亂switch (region) {case topLeftCorner:case rightBottomConrner:setCursor(Qt::SizeFDiagCursor);//設(shè)置光標(biāo)的形狀使用setCursor(),使用setShape()設(shè)置不上,并不知為啥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("鼠標(biāo)移動(dòng)的位置:")<<event->globalPos()<<QStringLiteral("按下點(diǎn)位置:")<<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;}//設(shè)置拉伸的最小寬度和高度if (rect.width() < 200 || rect.height() < 100) {return ;}setGeometry(rect);m_lastPos = event->globalPos(); }//void Widget::setMouseCursorStyle(QMouseEvent *event) //{ // //轉(zhuǎn)換后存在誤差,鼠標(biāo)在左下角獲取的位置與左下角的位置不一樣,因而無(wú)法實(shí)現(xiàn)下述方法 // qDebug()<<QStringLiteral("鼠標(biāo)在父窗口的位置:")<<mapFromParent(event->globalPos())<< // QStringLiteral("鼠標(biāo)的位置:")<<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("轉(zhuǎn)換后左下角")<<mapFromParent(geometry().bottomLeft());//獲取位置相同,都是鼠標(biāo)在父窗口中的位置 // 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("鼠標(biāo)在左上角"); // 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文件也采用默認(rèn)生成的文件。
這樣就可以編譯,運(yùn)行,查看程序的運(yùn)行效果了。
注意點(diǎn)
總結(jié)
以上是生活随笔為你收集整理的无标题栏窗口的实现拖动,和边的拉伸功能的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。