赞
踩
目录
由于QT对修改标题栏样式的支持有限,处于美化的考虑常常会使用使用无边框模式,并自己设计标题栏样式。
使用 setWindowFlag(Qt::FramelessWindowHint); 关闭QT窗口边框后,也会导致窗口拉伸缩放功能失效。
因此,需要使用自定义边框的方式,来实现窗口的拉升缩放。
对于自定义边框样式,网上的方案有很多,但是归根结底都是一个基本思路
捕获鼠标位置→在指定位置显示指定的鼠标样式→点击后捕获当前的点击位置→鼠标移动,依据点击的位置,计算位移→将位移反馈给窗体→窗体依据位移进行缩放拉伸→鼠标释放,释放捕获。
MyBorder.h
- #ifndef MYLABEL_H
- #define MYLABEL_H
-
- #include <QObject>
- #include <QLabel>
- #include <QMouseEvent>
- #include <qnamespace.h>
- class MyBorder:public QLabel
- {
- Q_OBJECT
- public:
- MyBorder(QWidget *parent=nullptr);
- void setScaleCursor(int nshape = 0);
- void mousePressEvent(QMouseEvent *ev);
- void mouseMoveEvent(QMouseEvent *ev);
- void mouseReleaseEvent(QMouseEvent *ev);
- QPoint m_mousePointOld;
- bool m_bKeepDrag;
- signals:
- void moveEventSig(QPoint point);
- void mouseReleasedSig();
- };
-
- #endif // MYLABEL_H
MyBorder.cpp
- #include "MyBorder.h"
-
- MyBorder::MyBorder(QWidget *parent):m_bKeepDrag(false)
- {
- this->setParent(parent);
- }
-
- void MyBorder::setScaleCursor(int nshape)
- {
- if(nshape == 1)//左右拉伸
- {
- setCursor(Qt::SizeHorCursor); //改变光标形状
- }
- else if(nshape == 2)//上下拉伸
- {
- setCursor(Qt::SizeVerCursor);
- }
- else if(nshape == 3)//右下拉伸
- {
- setCursor(Qt::SizeFDiagCursor);
- }
- else if(nshape == 4)//左下拉伸
- {
- setCursor(Qt::SizeBDiagCursor);
- }
- else //正常显示
- {
- setCursor(Qt::ArrowCursor);
- }
-
- }
-
- void MyBorder::mousePressEvent(QMouseEvent *ev)
- {
- if(ev->button() == Qt::LeftButton)
- {
- m_bKeepDrag = true; //拉伸标志
- m_mousePointOld = ev->globalPos();
- }
- }
-
- void MyBorder::mouseMoveEvent(QMouseEvent *ev)
- {
- if(m_bKeepDrag)
- {
- const QPoint position = ev->globalPos() - m_mousePointOld; //the position of mainfrmae + (current_mouse_position - last_mouse_position)
- //move(position.x(), position.y());
- emit moveEventSig(position);
- m_mousePointOld = ev->globalPos();
- }
- }
-
- void MyBorder::mouseReleaseEvent(QMouseEvent *ev)
- {
- Q_UNUSED(ev)
- m_bKeepDrag = false;
- }
mainwindow.h
- #ifndef MAINWINDOW_H
- #define MAINWINDOW_H
-
- #include <QMainWindow>
-
- #include <MyBorder/MyBorder.h>
-
- QT_BEGIN_NAMESPACE
- namespace Ui { class MainWindow; }
- QT_END_NAMESPACE
-
- class MainWindow : public QMainWindow
- {
- Q_OBJECT
-
- public:
- MainWindow(QWidget *parent = nullptr);
- ~MainWindow();
-
- private slots:
- void getLeftScaleEvent(QPoint movPoint);
-
- void getRightScaleEvent(QPoint movPoint);
-
- void getBottomScaleEvent(QPoint movPoint);
-
- void getTopScaleEvent(QPoint movPoint);
-
- void getRBScaleEvent(QPoint movPoint);
-
- void getRTScaleEvent(QPoint movPoint);
-
- void getLTScaleEvent(QPoint movPoint);
-
- void getLBScaleEvent(QPoint movPoint);
- private:
- void DarwBorder();
- void InitBorder();
- uint16_t minWindowHeight; //最小窗口高度
- uint16_t minWindowWidth; //最小窗口宽度
- //边框控件
- MyBorder *labelLft;
- MyBorder *labelRit;
- MyBorder *labelBot;
- MyBorder *labelTop;
- MyBorder *labelRB;
- MyBorder *labelRT;
- MyBorder *labelLB;
- MyBorder *labelLT;
- Ui::MainWindow *ui;
- };
- #endif // MAINWINDOW_H
mainwindow.cpp
- #include "mainwindow.h"
- #include "ui_mainwindow.h"
-
- MainWindow::MainWindow(QWidget *parent)
- : QMainWindow(parent)
- , ui(new Ui::MainWindow)
- {
- ui->setupUi(this);
- setWindowFlag(Qt::FramelessWindowHint);
- InitBorder();
- }
-
- MainWindow::~MainWindow()
- {
- delete ui;
- }
-
-
- //初始化左右边框
- void MainWindow::InitBorder()
- {
- minWindowWidth = 1000; //最小窗口宽度
- minWindowHeight = 650; //最小窗口高度
-
-
- //上下左右的label,为了控制界面能够拖动拉伸
- labelLft = new MyBorder(this);
- labelLft->setStyleSheet("QLabel {background-color: transparent;}");//设置背景透明
- labelLft->raise();
- labelLft->setScaleCursor(1);
-
-
- labelRit = new MyBorder(this);
- labelRit->setStyleSheet("QLabel {background-color: transparent;}");//设置背景透明
- labelRit->raise();
- labelRit->setScaleCursor(1);//设置为左右拉升光标
-
-
- labelBot = new MyBorder(this);
- labelBot->setStyleSheet("QLabel {background-color: transparent;}");//设置背景透明
- labelBot->raise();
- labelBot->setScaleCursor(2);//设置为上下拉升光标
-
-
- labelTop = new MyBorder(this);
- labelTop->setStyleSheet("QLabel {background-color: transparent;}");//设置背景透明
- labelTop->setScaleCursor(2);//设置为上下拉升光标
-
- labelRB = new MyBorder(this);
- labelRB->setStyleSheet("QLabel {background-color: transparent;}");//设置背景透明
- labelRB->setScaleCursor(3);//设置为右下拉升光标
-
- labelRT = new MyBorder(this);
- labelRT->setStyleSheet("QLabel {background-color: transparent;}");//设置背景透明
- labelRT->setScaleCursor(4);//设置为右上拉升光标
-
- labelLB = new MyBorder(this);
- labelLB->setStyleSheet("QLabel {background-color: transparent;}");//设置背景透明
- labelLB->setScaleCursor(4);//设置为左下拉升光标
-
- labelLT = new MyBorder(this);
- labelLT->setStyleSheet("QLabel {background-color: transparent;}");//设置背景透明
- labelLT->setScaleCursor(3);//设置为左上拉升光标
-
- //绘制边框
- DarwBorder();
-
- //关联回调函数
- connect(labelLft, SIGNAL(moveEventSig(QPoint)), this, SLOT(getLeftScaleEvent(QPoint)));
- connect(labelRit, SIGNAL(moveEventSig(QPoint)), this, SLOT(getRightScaleEvent(QPoint)));
- connect(labelBot, SIGNAL(moveEventSig(QPoint)), this, SLOT(getBottomScaleEvent(QPoint)));
- connect(labelTop, SIGNAL(moveEventSig(QPoint)), this, SLOT(getTopScaleEvent(QPoint)));
- connect(labelRB, SIGNAL(moveEventSig(QPoint)), this, SLOT(getRBScaleEvent(QPoint)));
- connect(labelRT, SIGNAL(moveEventSig(QPoint)), this, SLOT(getRTScaleEvent(QPoint)));
- connect(labelLB, SIGNAL(moveEventSig(QPoint)), this, SLOT(getLBScaleEvent(QPoint)));
- connect(labelLT, SIGNAL(moveEventSig(QPoint)), this, SLOT(getLTScaleEvent(QPoint)));
- }
-
- //重绘边框
- void MainWindow::DarwBorder()
- {
- labelLft->setGeometry(0,0,5,this->height());
- labelRit->setGeometry(this->width()-5,0,5,this->height());
- labelBot->setGeometry(0,this->height()-5,this->width(),5);
- labelTop->setGeometry(0,0,this->width(),5);
- labelRB->setGeometry(this->width()-6,this->height()-6,this->width(),this->height());
- labelRT->setGeometry(this->width()-6,0,this->width(),6);
- labelLB->setGeometry(0,this->height()-6,6,this->width());
- labelLT->setGeometry(0,0,6,6);
- }
-
- void MainWindow::getLeftScaleEvent(QPoint movPoint)
- {
- if((pos().x()+movPoint.x())>(pos().x()+this->width()-minWindowWidth))
- {
- return;//保证拖动窗口左边界的时候,控件宽度至少有200
- }
- this->setGeometry(pos().x()+movPoint.x(),pos().y(),this->width()-movPoint.x(),this->height());
- DarwBorder();
- }
-
- void MainWindow::getRightScaleEvent(QPoint movPoint)
- {
- if((pos().x()+this->width()+movPoint.x())<(pos().x()+minWindowWidth))
- {
- return;//保证拖动窗口右边界的时候,控件宽度至少有200
- }
- this->setGeometry(pos().x(),pos().y(),this->width()+movPoint.x(),this->height());
- DarwBorder();
- }
-
- void MainWindow::getBottomScaleEvent(QPoint movPoint)
- {
- if((pos().y()+this->height()+movPoint.y())<(pos().y()+minWindowHeight))
- {
- return;//保证拖动窗口下边界的时候,控件高度至少有200
- }
- this->setGeometry(pos().x(),pos().y(),this->width(),this->height()+movPoint.y());
- DarwBorder();
- }
-
- void MainWindow::getTopScaleEvent(QPoint movPoint)
- {
- if((pos().y()+movPoint.y())>(pos().y()+this->height()-minWindowHeight))
- {
- return;//保证拖动窗口上边界的时候,控件高度至少有200
- }
- this->setGeometry(pos().x(),pos().y()+movPoint.y(),this->width(),this->height()-movPoint.y());
- DarwBorder();
- }
-
- void MainWindow::getRBScaleEvent(QPoint movPoint)
- {
- if((pos().y()+this->height()+movPoint.y())<(pos().y()+minWindowHeight)
- || (pos().x()+this->width()+movPoint.x())<(pos().x()+minWindowWidth))
- {
- return;//保证拖动窗口上边界的时候,控件高度和宽度至少有200
- }
- this->setGeometry(pos().x(),pos().y(),this->width()+movPoint.x(),this->height());
- this->setGeometry(pos().x(),pos().y(),this->width(),this->height()+movPoint.y());
- DarwBorder();
- }
-
- void MainWindow::getRTScaleEvent(QPoint movPoint)
- {
- if((pos().x()+this->width()+movPoint.x())<(pos().x()+minWindowWidth)
- || (pos().y()+movPoint.y())>(pos().y()+this->height()-minWindowHeight) )
- {
- return;//保证拖动窗口上边界的时候,控件高度和宽度至少有200
- }
- this->setGeometry(pos().x(),pos().y()+movPoint.y(),this->width(),this->height()-movPoint.y());
- this->setGeometry(pos().x(),pos().y(),this->width()+movPoint.x(),this->height());
- DarwBorder();
- }
-
- void MainWindow::getLTScaleEvent(QPoint movPoint)
- {
- if((pos().x()+movPoint.x())>(pos().x()+this->width()-minWindowWidth)
- || (pos().y()+movPoint.y())>(pos().y()+this->height()-minWindowHeight) )
- {
- return;//保证拖动窗口上边界的时候,控件高度和宽度至少有200
- }
- this->setGeometry(pos().x()+movPoint.x(),pos().y(),this->width()-movPoint.x(),this->height());
- this->setGeometry(pos().x(),pos().y()+movPoint.y(),this->width(),this->height()-movPoint.y());
- DarwBorder();
- }
-
- void MainWindow::getLBScaleEvent(QPoint movPoint)
- {
- if((pos().x()+movPoint.x())>(pos().x()+this->width()-minWindowWidth)
- || (pos().y()+this->height()+movPoint.y())<(pos().y()+minWindowHeight))
- {
- return;//保证拖动窗口上边界的时候,控件高度和宽度至少有200
- }
- this->setGeometry(pos().x()+movPoint.x(),pos().y(),this->width()-movPoint.x(),this->height());
- this->setGeometry(pos().x(),pos().y(),this->width(),this->height()+movPoint.y());
- DarwBorder();
- }
通过重写QLabel中的鼠标点击事件,鼠标移动事件,鼠标释放事件三个事件,并将QLabel绘制在主窗口的特定位置。特定事件产生时,将相关参数通过信号的方式传递给主窗口,从而控制主窗口进行拉伸缩放。
使用这种方式,能够实现自定义缩放功能没错,但是也有明显的缺点,和直接重现主窗口中的三个鼠标事件的方式一样(网上有这种方式),每个多一个新窗口都需要在新窗口的代码中重写一次初始化函数,关联回调函数等操作,就算是复制粘贴,窗口一多也会显得十分的麻烦。
因此,我们需要加入一点点细节,来解决这个问题,下面请看参考程序2。
MyBorder.h
- #ifndef MYLABEL_H
- #define MYLABEL_H
-
- #include <QObject>
- #include <QLabel>
- #include <QMouseEvent>
- #include <qnamespace.h>
-
- class MyBorder:public QLabel
- {
- Q_OBJECT
- public:
- MyBorder(QWidget *parent=nullptr);
- void setScaleCursor(int nshape = 0);
- void mousePressEvent(QMouseEvent *ev);
- void mouseMoveEvent(QMouseEvent *ev);
- void mouseReleaseEvent(QMouseEvent *ev);
- QPoint m_mousePointOld;
- bool m_bKeepDrag;
- signals:
- void moveEventSig(QPoint point);
- void mouseReleasedSig();
- };
-
- #endif // MYLABEL_H
MyBorder.cpp
- #include "MyBorder.h"
-
- MyBorder::MyBorder(QWidget *parent):m_bKeepDrag(false)
- {
- this->setParent(parent);
- }
-
- void MyBorder::setScaleCursor(int nshape)
- {
- if(nshape == 1)//左右拉伸
- {
- setCursor(Qt::SizeHorCursor); //改变光标形状
- }
- else if(nshape == 2)//上下拉伸
- {
- setCursor(Qt::SizeVerCursor);
- }
- else if(nshape == 3)//右下拉伸
- {
- setCursor(Qt::SizeFDiagCursor);
- }
- else if(nshape == 4)//左下拉伸
- {
- setCursor(Qt::SizeBDiagCursor);
- }
- else //正常显示
- {
- setCursor(Qt::ArrowCursor);
- }
-
- }
-
- void MyBorder::mousePressEvent(QMouseEvent *ev)
- {
- if(ev->button() == Qt::LeftButton)
- {
- m_bKeepDrag = true;
- m_mousePointOld = ev->globalPos();
- }
- }
-
- void MyBorder::mouseMoveEvent(QMouseEvent *ev)
- {
- if(m_bKeepDrag)
- {
- const QPoint position = ev->globalPos() - m_mousePointOld; //the position of mainfrmae + (current_mouse_position - last_mouse_position)
- //move(position.x(), position.y());
- emit moveEventSig(position);
- m_mousePointOld = ev->globalPos();
- }
- }
-
- void MyBorder::mouseReleaseEvent(QMouseEvent *ev)
- {
- Q_UNUSED(ev)
- m_bKeepDrag = false;
- }
MyBorderContainer.h
- #ifndef MYBORDERCONTAINER_H
- #define MYBORDERCONTAINER_H
-
- #include "MyBorder.h"
-
- #include <QWidget>
- #include <QObject>
- #include <QLabel>
- #include <QMouseEvent>
-
-
- class MyBorderContainer : public QObject
- {
- Q_OBJECT
- public:
- MyBorderContainer(QWidget *parent,uint16_t minWindowHeight = 50, uint16_t minWindowWidth = 50, uint16_t borderSize = 5);
- void setMinWindowSize(uint16_t minWindowWidth, uint16_t minWindowHeight); //设置窗口最小尺寸
- void setBorderSize(uint16_t borderSize); //设置边框捕获区域尺寸
- void DarwBorder();
- protected:
- void InitBorder();
-
- private slots:
- void getLeftScaleEvent(QPoint movPoint);
-
- void getRightScaleEvent(QPoint movPoint);
-
- void getBottomScaleEvent(QPoint movPoint);
-
- void getTopScaleEvent(QPoint movPoint);
-
- void getRBScaleEvent(QPoint movPoint);
-
- void getRTScaleEvent(QPoint movPoint);
-
- void getLTScaleEvent(QPoint movPoint);
-
- void getLBScaleEvent(QPoint movPoint);
-
- private:
-
- uint16_t minWindowHeight; //最小窗口高度
- uint16_t minWindowWidth; //最小窗口宽度
- uint16_t borderSize;
- QWidget *forms;
- //边框控件
- MyBorder *labelLft;
- MyBorder *labelRit;
- MyBorder *labelBot;
- MyBorder *labelTop;
- MyBorder *labelRB;
- MyBorder *labelRT;
- MyBorder *labelLB;
- MyBorder *labelLT;
- };
-
- #endif // MYBORDERCONTAINER_H
MyBorderContainer.cpp
- #include "MyBorderContainer.h"
- MyBorderContainer::MyBorderContainer(QWidget *parent,uint16_t minWindowHeight,uint16_t minWindowWidth, uint16_t borderSize)
- {
- forms = parent;
- this->minWindowHeight = minWindowHeight; //最小窗口高度
- this->minWindowWidth = minWindowWidth; //最小窗口宽度
- this->borderSize = borderSize;
- this->setParent(parent);
- InitBorder();
- }
-
-
- void MyBorderContainer::InitBorder()
- {
- //上下左右的label,为了控制界面能够拖动拉伸
- labelLft = new MyBorder(forms);
- labelLft->setStyleSheet("QLabel {background-color: transparent;}");//设置背景透明
- labelLft->raise();
- labelLft->setScaleCursor(1);
- connect(labelLft, SIGNAL(moveEventSig(QPoint)), this, SLOT(getLeftScaleEvent(QPoint)));
-
- labelRit = new MyBorder(forms);
- labelRit->setStyleSheet("QLabel {background-color: transparent;}");//设置背景透明
- labelRit->raise();
- labelRit->setScaleCursor(1);//设置为左右拉升光标
- connect(labelRit, SIGNAL(moveEventSig(QPoint)), this, SLOT(getRightScaleEvent(QPoint)));
-
- labelBot = new MyBorder(forms);
- labelBot->setStyleSheet("QLabel {background-color: transparent;}");//设置背景透明
- labelBot->raise();
- labelBot->setScaleCursor(2);//设置为上下拉升光标
- connect(labelBot, SIGNAL(moveEventSig(QPoint)), this, SLOT(getBottomScaleEvent(QPoint)));
-
- labelTop = new MyBorder(forms);
- labelTop->setStyleSheet("QLabel {background-color: transparent;}");//设置背景透明
- labelTop->raise();
- labelTop->setScaleCursor(2);//设置为上下拉升光标
- connect(labelTop, SIGNAL(moveEventSig(QPoint)), this, SLOT(getTopScaleEvent(QPoint)));
-
- labelRB = new MyBorder(forms);
- labelRB->setStyleSheet("QLabel {background-color: transparent;}");//设置背景透明
- labelRB->raise();
- labelRB->setScaleCursor(3);//设置为右下拉升光标
- connect(labelRB, SIGNAL(moveEventSig(QPoint)), this, SLOT(getRBScaleEvent(QPoint)));
-
- labelRT = new MyBorder(forms);
- labelRT->setStyleSheet("QLabel {background-color: transparent;}");//设置背景透明
- labelRT->raise();
- labelRT->setScaleCursor(4);//设置为右上拉升光标
- connect(labelRT, SIGNAL(moveEventSig(QPoint)), this, SLOT(getRTScaleEvent(QPoint)));
-
- labelLB = new MyBorder(forms);
- labelLB->setStyleSheet("QLabel {background-color: transparent;}");//设置背景透明
- labelLB->raise();
- labelLB->setScaleCursor(4);//设置为左下拉升光标
- connect(labelLB, SIGNAL(moveEventSig(QPoint)), this, SLOT(getLBScaleEvent(QPoint)));
-
- labelLT = new MyBorder(forms);
- labelLT->setStyleSheet("QLabel {background-color: transparent;}");//设置背景透明
- labelLT->raise();
- labelLT->setScaleCursor(3);//设置为左上拉升光标
- connect(labelLT, SIGNAL(moveEventSig(QPoint)), this, SLOT(getLTScaleEvent(QPoint)));
-
- DarwBorder();
- }
-
- void MyBorderContainer::setMinWindowSize(uint16_t minWindowWidth, uint16_t minWindowHeight)
- {
- this->minWindowHeight = minWindowHeight; //最小窗口高度
- this->minWindowWidth = minWindowWidth; //最小窗口宽度
- }
-
- void MyBorderContainer::setBorderSize(uint16_t borderSize)
- {
- this->borderSize = borderSize;
- }
-
- //重绘边框
- void MyBorderContainer::DarwBorder()
- {
- labelLft->setGeometry(0,0,this->borderSize,forms->height());
- labelRit->setGeometry(forms->width()-this->borderSize,0,this->borderSize,forms->height());
- labelBot->setGeometry(0,forms->height()-this->borderSize,forms->width(),this->borderSize);
- labelTop->setGeometry(0,0,forms->width(),this->borderSize);
- labelRB->setGeometry(forms->width()-this->borderSize-1,forms->height()-this->borderSize-1,forms->width(),forms->height());
- labelRT->setGeometry(forms->width()-this->borderSize-1,0,forms->width(),this->borderSize+1);
- labelLB->setGeometry(0,forms->height()-this->borderSize-1,this->borderSize+1,forms->width());
- labelLT->setGeometry(0,0,this->borderSize+1,this->borderSize+1);
- }
-
- void MyBorderContainer::getLeftScaleEvent(QPoint movPoint)
- {
- if((forms->pos().x()+movPoint.x())>(forms->pos().x()+forms->width()-minWindowWidth))
- {
- return;//保证拖动窗口左边界的时候,控件宽度至少有最小值
- }
- forms->setGeometry(forms->pos().x()+movPoint.x(),forms->pos().y(),forms->width()-movPoint.x(),forms->height());
- DarwBorder();
- }
-
- void MyBorderContainer::getRightScaleEvent(QPoint movPoint)
- {
- if((forms->pos().x()+forms->width()+movPoint.x())<(forms->pos().x()+minWindowWidth))
- {
- return;//保证拖动窗口右边界的时候,控件宽度至少有最小值
- }
- forms->setGeometry(forms->pos().x(),forms->pos().y(),forms->width()+movPoint.x(),forms->height());
- DarwBorder();
- }
-
- void MyBorderContainer::getBottomScaleEvent(QPoint movPoint)
- {
- if((forms->pos().y()+forms->height()+movPoint.y())<(forms->pos().y()+minWindowHeight))
- {
- return;//保证拖动窗口下边界的时候,控件高度至少有最小值
- }
- forms->setGeometry(forms->pos().x(),forms->pos().y(),forms->width(),forms->height()+movPoint.y());
- DarwBorder();
- }
-
- void MyBorderContainer::getTopScaleEvent(QPoint movPoint)
- {
- if((forms->pos().y()+movPoint.y())>(forms->pos().y()+forms->height()-minWindowHeight))
- {
- return;//保证拖动窗口上边界的时候,控件高度至少有最小值
- }
- forms->setGeometry(forms->pos().x(),forms->pos().y()+movPoint.y(),forms->width(),forms->height()-movPoint.y());
- DarwBorder();
- }
-
- void MyBorderContainer::getRBScaleEvent(QPoint movPoint)
- {
- if((forms->pos().y()+forms->height()+movPoint.y())<(forms->pos().y()+minWindowHeight)
- || (forms->pos().x()+forms->width()+movPoint.x())<(forms->pos().x()+minWindowWidth))
- {
- return;//保证拖动窗口上边界的时候,控件高度和宽度至少有最小值
- }
- forms->setGeometry(forms->pos().x(),forms->pos().y(),forms->width()+movPoint.x(),forms->height());
- forms->setGeometry(forms->pos().x(),forms->pos().y(),forms->width(),forms->height()+movPoint.y());
- DarwBorder();
- }
-
- void MyBorderContainer::getRTScaleEvent(QPoint movPoint)
- {
- if((forms->pos().x()+forms->width()+movPoint.x())<(forms->pos().x()+minWindowWidth)
- || (forms->pos().y()+movPoint.y())>(forms->pos().y()+forms->height()-minWindowHeight) )
- {
- return;//保证拖动窗口上边界的时候,控件高度和宽度至少有最小值
- }
- forms->setGeometry(forms->pos().x(),forms->pos().y()+movPoint.y(),forms->width(),forms->height()-movPoint.y());
- forms->setGeometry(forms->pos().x(),forms->pos().y(),forms->width()+movPoint.x(),forms->height());
- DarwBorder();
- }
-
- void MyBorderContainer::getLTScaleEvent(QPoint movPoint)
- {
- if((forms->pos().x()+movPoint.x())>(forms->pos().x()+forms->width()-minWindowWidth)
- || (forms->pos().y()+movPoint.y())>(forms->pos().y()+forms->height()-minWindowHeight) )
- {
- return;//保证拖动窗口上边界的时候,控件高度和宽度至少有最小值
- }
- forms->setGeometry(forms->pos().x()+movPoint.x(),forms->pos().y(),forms->width()-movPoint.x(),forms->height());
- forms->setGeometry(forms->pos().x(),forms->pos().y()+movPoint.y(),forms->width(),forms->height()-movPoint.y());
- DarwBorder();
- }
-
- void MyBorderContainer::getLBScaleEvent(QPoint movPoint)
- {
- if((forms->pos().x()+movPoint.x())>(forms->pos().x()+forms->width()-minWindowWidth)
- || (forms->pos().y()+forms->height()+movPoint.y())<(forms->pos().y()+minWindowHeight))
- {
- return;//保证拖动窗口上边界的时候,控件高度和宽度至少有最小值
- }
- forms->setGeometry(forms->pos().x()+movPoint.x(),forms->pos().y(),forms->width()-movPoint.x(),forms->height());
- forms->setGeometry(forms->pos().x(),forms->pos().y(),forms->width(),forms->height()+movPoint.y());
- DarwBorder();
- }
mainwindow.h
- #ifndef MAINWINDOW_H
- #define MAINWINDOW_H
-
- #include <MyBorder/MyBorderContainer.h>
- #include <QMainWindow>
-
- namespace Ui {
- class MainWindow;
- }
-
- class MainWindow : public QMainWindow
- {
- Q_OBJECT
-
- public:
- explicit MainWindow(QWidget *parent = 0);
- ~MainWindow();
- private:
- Ui::MainWindow *ui;
-
- private:
- MyBorderContainer *My;
-
- };
-
- #endif // MAINWINDOW_H
mainwindow.cpp
- #include "mainwindow.h"
- #include "ui_mainwindow.h"
-
- MainWindow::MainWindow(QWidget *parent) :
- QMainWindow(parent),
- ui(new Ui::MainWindow)
- {
- ui->setupUi(this);
- setWindowFlag(Qt::FramelessWindowHint);
- My = new MyBorderContainer(this);
- }
-
- MainWindow::~MainWindow()
- {
- delete ui;
- }
-
-
实现思路与参考程序1基本相同,不同点在于该程序对程序1进行了一层封装。建立一个边框管理类(MyBorderContainer),用于生成和管理边框。将特定的窗体指针传递给边框管理类进行托管即可。
优点:相较于程序1,该程序只需要在窗体中创建一个边框管理类(MyBorderContainer),然后将自己的指针(this)传递给边框管理类进行托管即可。
一行代码解决问题的感觉确实很爽呢。
缺点:虽然对边框类进行了封装,但是由于边框类(MyBorder)依旧是一个独立的类,能够在其他类(除了MyBorderContainer以外)方法中创建。通常,这并不是我们想要的。
因此,我们可以再加入一点点小细节,来解决这个问题,下面请看参考程序3。
MyBorderContainer.h
- #ifndef MYBORDERCONTAINER_H
- #define MYBORDERCONTAINER_H
-
- #include <QWidget>
- #include <QObject>
- #include <QLabel>
- #include <QMouseEvent>
-
- enum BorderType
- {
- NULL_BORDER = 0, // 无
- L_BORDER, // 左
- R_BORDER, // 右
- T_BORDER, // 上
- B_BORDER, // 下
- LT_BORDER, // 左上
- LB_BORDER, //左下
- RT_BORDER, //右上
- RB_BORDER, //右下
- };
-
-
- class MyBorderContainer : public QObject
- {
- Q_OBJECT
- public:
- MyBorderContainer(QWidget *parent,uint16_t minWindowHeight = 50, uint16_t minWindowWidth = 50, uint16_t borderSize = 5);
- void setMinWindowSize(uint16_t minWindowWidth, uint16_t minWindowHeight); //设置窗口最小尺寸
- void setBorderSize(uint16_t borderSize); //设置边框捕获区域尺寸
- void DarwBorder(); //重新绘制边框(调整位置)
-
- protected:
- void InitBorder(); //初始化边框
-
- private:
- void getLeftScaleEvent(QPoint movPoint);
-
- void getRightScaleEvent(QPoint movPoint);
-
- void getBottomScaleEvent(QPoint movPoint);
-
- void getTopScaleEvent(QPoint movPoint);
-
- void getRBScaleEvent(QPoint movPoint);
-
- void getRTScaleEvent(QPoint movPoint);
-
- void getLTScaleEvent(QPoint movPoint);
-
- void getLBScaleEvent(QPoint movPoint);
- //内部边框类,防止外部创建
- class MyBorder:public QLabel
- {
- public:
- //设置边框属性
- MyBorder(QWidget *parent, BorderType type, MyBorderContainer * outClass);
- protected:
- void mousePressEvent(QMouseEvent *ev);
- void mouseMoveEvent(QMouseEvent *ev);
- void mouseReleaseEvent(QMouseEvent *ev);
-
- private:
- MyBorderContainer *container; //保存外部类指针
- BorderType MyType;
- QPoint mousePointOld;
- bool KeepDrag;
- };
-
- uint16_t borderSize; //边框捕获区大小
- uint16_t minWindowHeight; //最小窗口高度
- uint16_t minWindowWidth; //最小窗口宽度
-
- QWidget *m_widget;
- //边框控件
- MyBorder *labelLft;
- MyBorder *labelRit;
- MyBorder *labelBot;
- MyBorder *labelTop;
- MyBorder *labelRB;
- MyBorder *labelRT;
- MyBorder *labelLB;
- MyBorder *labelLT;
- };
-
- #endif // MYBORDERCONTAINER_H
MyBorder.cpp
- #include "MyBorderContainer.h"
-
- MyBorderContainer::MyBorder::MyBorder(QWidget *parent, BorderType type, MyBorderContainer * contex)
- {
- this->setParent(parent);
- KeepDrag = false;
- MyType = type;
- container = contex;
- if(MyType == L_BORDER || MyType == R_BORDER)
- {
- setCursor(Qt::SizeHorCursor);
- }
- else if(MyType == T_BORDER || MyType == B_BORDER)
- {
- setCursor(Qt::SizeVerCursor);
- }
- else if(MyType == LT_BORDER || MyType == RB_BORDER)
- {
- setCursor(Qt::SizeFDiagCursor);
- }
- else if(MyType == LB_BORDER || MyType == RT_BORDER)
- {
- setCursor(Qt::SizeBDiagCursor);
- }
- else
- {
- setCursor(Qt::ArrowCursor);
- }
- }
-
- //鼠标点击事件
- void MyBorderContainer::MyBorder::mousePressEvent(QMouseEvent *ev)
- {
- if(ev->button() == Qt::LeftButton)
- {
- KeepDrag = true;
- mousePointOld = ev->globalPos();
- }
- return QWidget::mousePressEvent(ev);
- }
-
- //鼠标移动事件
- void MyBorderContainer::MyBorder::mouseMoveEvent(QMouseEvent *ev)
- {
- if(KeepDrag)
- {
- const QPoint position = ev->globalPos() - mousePointOld;
-
- //调用外部类接口
- switch (MyType) {
- case L_BORDER: //左
- container->getLeftScaleEvent(position);
- break;
- case R_BORDER: //右
- container->getRightScaleEvent(position);
- break;
- case T_BORDER: //上
- container->getTopScaleEvent(position);
- break;
- case B_BORDER: //上
- container->getBottomScaleEvent(position);
- break;
- case RB_BORDER: //右下
- container->getRBScaleEvent(position);
- break;
- case RT_BORDER: //右上
- container->getRTScaleEvent(position);
- break;
- case LB_BORDER: //左下
- container->getLBScaleEvent(position);
- break;
- case LT_BORDER: //左上
- container->getLTScaleEvent(position);
- break;
- default:
- break;
- }
- mousePointOld = ev->globalPos();
- }
- return QWidget::mouseMoveEvent(ev);
- }
-
- //鼠标释放事件
- void MyBorderContainer::MyBorder::mouseReleaseEvent(QMouseEvent *ev)
- {
- Q_UNUSED(ev)
- KeepDrag = false;
- return QWidget::mouseReleaseEvent(ev);
- }
MyBorderContainer.cpp
- #include "MyBorderContainer.h"
- MyBorderContainer::MyBorderContainer(QWidget *parent,uint16_t minWindowHeight,uint16_t minWindowWidth, uint16_t borderSize)
- {
- m_widget = parent;
- this->minWindowHeight = minWindowHeight; //最小窗口高度
- this->minWindowWidth = minWindowWidth; //最小窗口宽度
- this->borderSize = borderSize;
- this->setParent(parent);
- InitBorder();
- }
-
- void MyBorderContainer::InitBorder()
- {
- //上下左右的label,为了控制界面能够拖动拉伸
- labelLft = new MyBorder(m_widget, L_BORDER, this);
- labelLft->setStyleSheet("QLabel {background-color: transparent;}");//设置背景透明
- labelLft->raise();
-
-
- labelRit = new MyBorder(m_widget, R_BORDER, this);
- labelRit->setStyleSheet("QLabel {background-color: transparent;}");//设置背景透明
- labelRit->raise();
-
- labelBot = new MyBorder(m_widget, B_BORDER, this);
- labelBot->setStyleSheet("QLabel {background-color: transparent;}");//设置背景透明
- labelBot->raise();
-
- labelTop = new MyBorder(m_widget, T_BORDER, this);
- labelTop->setStyleSheet("QLabel {background-color: transparent;}");//设置背景透明
- labelTop->raise();
-
-
- labelRB = new MyBorder(m_widget, RB_BORDER, this);
- labelRB->setStyleSheet("QLabel {background-color: transparent;}");//设置背景透明
- labelRB->raise();
-
-
- labelRT = new MyBorder(m_widget, RT_BORDER, this);
- labelRT->setStyleSheet("QLabel {background-color: transparent;}");//设置背景透明
- labelRT->raise();
-
-
- labelLB = new MyBorder(m_widget, LB_BORDER, this);
- labelLB->setStyleSheet("QLabel {background-color: transparent;}");//设置背景透明
- labelLB->raise();
-
- labelLT = new MyBorder(m_widget, LT_BORDER, this);
- labelLT->setStyleSheet("QLabel {background-color: transparent;}");//设置背景透明
- labelLT->raise();
-
- DarwBorder();
- }
-
- void MyBorderContainer::setMinWindowSize(uint16_t minWindowWidth, uint16_t minWindowHeight)
- {
- this->minWindowHeight = minWindowHeight; //最小窗口高度
- this->minWindowWidth = minWindowWidth; //最小窗口宽度
- }
-
- void MyBorderContainer::setBorderSize(uint16_t borderSize)
- {
- this->borderSize = borderSize;
- }
-
- //重绘边框
- void MyBorderContainer::DarwBorder()
- {
- labelLft->setGeometry(0,0,this->borderSize,m_widget->height());
- labelRit->setGeometry(m_widget->width()-this->borderSize,0,this->borderSize,m_widget->height());
- labelBot->setGeometry(0,m_widget->height()-this->borderSize,m_widget->width(),this->borderSize);
- labelTop->setGeometry(0,0,m_widget->width(),this->borderSize);
- labelRB->setGeometry(m_widget->width()-this->borderSize-1,m_widget->height()-this->borderSize-1,m_widget->width(),m_widget->height());
- labelRT->setGeometry(m_widget->width()-this->borderSize-1,0,m_widget->width(),this->borderSize+1);
- labelLB->setGeometry(0,m_widget->height()-this->borderSize-1,this->borderSize+1,m_widget->width());
- labelLT->setGeometry(0,0,this->borderSize+1,this->borderSize+1);
- }
-
- void MyBorderContainer::getLeftScaleEvent(QPoint movPoint)
- {
- if((m_widget->pos().x()+movPoint.x())>(m_widget->pos().x()+m_widget->width()-minWindowWidth))
- {
- return;//保证拖动窗口左边界的时候,控件宽度至少有200
- }
- m_widget->setGeometry(m_widget->pos().x()+movPoint.x(),m_widget->pos().y(),m_widget->width()-movPoint.x(),m_widget->height());
- DarwBorder();
- }
-
- void MyBorderContainer::getRightScaleEvent(QPoint movPoint)
- {
- if((m_widget->pos().x()+m_widget->width()+movPoint.x())<(m_widget->pos().x()+minWindowWidth))
- {
- return;//保证拖动窗口右边界的时候,控件宽度至少有200
- }
- m_widget->setGeometry(m_widget->pos().x(),m_widget->pos().y(),m_widget->width()+movPoint.x(),m_widget->height());
- DarwBorder();
- }
-
- void MyBorderContainer::getBottomScaleEvent(QPoint movPoint)
- {
- if((m_widget->pos().y()+m_widget->height()+movPoint.y())<(m_widget->pos().y()+minWindowHeight))
- {
- return;//保证拖动窗口下边界的时候,控件高度至少有200
- }
- m_widget->setGeometry(m_widget->pos().x(),m_widget->pos().y(),m_widget->width(),m_widget->height()+movPoint.y());
- DarwBorder();
- }
-
- void MyBorderContainer::getTopScaleEvent(QPoint movPoint)
- {
- if((m_widget->pos().y()+movPoint.y())>(m_widget->pos().y()+m_widget->height()-minWindowHeight))
- {
- return;//保证拖动窗口上边界的时候,控件高度至少有200
- }
- m_widget->setGeometry(m_widget->pos().x(),m_widget->pos().y()+movPoint.y(),m_widget->width(),m_widget->height()-movPoint.y());
- DarwBorder();
- }
-
- void MyBorderContainer::getRBScaleEvent(QPoint movPoint)
- {
- if((m_widget->pos().y()+m_widget->height()+movPoint.y())<(m_widget->pos().y()+minWindowHeight)
- || (m_widget->pos().x()+m_widget->width()+movPoint.x())<(m_widget->pos().x()+minWindowWidth))
- {
- return;//保证拖动窗口上边界的时候,控件高度和宽度至少有200
- }
- m_widget->setGeometry(m_widget->pos().x(),m_widget->pos().y(),m_widget->width()+movPoint.x(),m_widget->height());
- m_widget->setGeometry(m_widget->pos().x(),m_widget->pos().y(),m_widget->width(),m_widget->height()+movPoint.y());
- DarwBorder();
- }
-
- void MyBorderContainer::getRTScaleEvent(QPoint movPoint)
- {
- if((m_widget->pos().x()+m_widget->width()+movPoint.x())<(m_widget->pos().x()+minWindowWidth)
- || (m_widget->pos().y()+movPoint.y())>(m_widget->pos().y()+m_widget->height()-minWindowHeight) )
- {
- return;//保证拖动窗口上边界的时候,控件高度和宽度至少有200
- }
- m_widget->setGeometry(m_widget->pos().x(),m_widget->pos().y()+movPoint.y(),m_widget->width(),m_widget->height()-movPoint.y());
- m_widget->setGeometry(m_widget->pos().x(),m_widget->pos().y(),m_widget->width()+movPoint.x(),m_widget->height());
- DarwBorder();
- }
-
- void MyBorderContainer::getLTScaleEvent(QPoint movPoint)
- {
- if((m_widget->pos().x()+movPoint.x())>(m_widget->pos().x()+m_widget->width()-minWindowWidth)
- || (m_widget->pos().y()+movPoint.y())>(m_widget->pos().y()+m_widget->height()-minWindowHeight) )
- {
- return;//保证拖动窗口上边界的时候,控件高度和宽度至少有200
- }
- m_widget->setGeometry(m_widget->pos().x()+movPoint.x(),m_widget->pos().y(),m_widget->width()-movPoint.x(),m_widget->height());
- m_widget->setGeometry(m_widget->pos().x(),m_widget->pos().y()+movPoint.y(),m_widget->width(),m_widget->height()-movPoint.y());
- DarwBorder();
- }
-
- void MyBorderContainer::getLBScaleEvent(QPoint movPoint)
- {
- if((m_widget->pos().x()+movPoint.x())>(m_widget->pos().x()+m_widget->width()-minWindowWidth)
- || (m_widget->pos().y()+m_widget->height()+movPoint.y())<(m_widget->pos().y()+minWindowHeight))
- {
- return;//保证拖动窗口上边界的时候,控件高度和宽度至少有200
- }
- m_widget->setGeometry(m_widget->pos().x()+movPoint.x(),m_widget->pos().y(),m_widget->width()-movPoint.x(),m_widget->height());
- m_widget->setGeometry(m_widget->pos().x(),m_widget->pos().y(),m_widget->width(),m_widget->height()+movPoint.y());
- DarwBorder();
- }
该程序将边框类(MyBorder)设置为边框管理类(MyBorderContainer)的内部类,这样就可以让外部无法创建MyBorder对象。
参考程序3进一步加深了程序的封装程度,将MyBorder.h和MyBorderContainer.h以及MyBorderContainer.cpp三个文件打包后,就可以当做一个模块来使用了,非常方便,当然封装有利有弊,应该根据实际需要进行选择。
目前以及将参考程序3打包成模块,并编写了简单的Demo上传至GitHub上
链接:BorderDemo
将其中的BorderDemo.pro文件导入Qt Creator并选择自己的编译器即可使用。
不论你选择以上3种程序的哪种方案,亦或者网上的其他方案,都不重要。相比于纠结哪种实现过程,实现的思路更为重要。编程时,多思考因为-所以才是最快乐的。
什么?你还想要窗体可以拖动?那当然是封装一个标题栏啦!(待更新)
如果你有什么不懂的地方,亦或者发现博主某个地方存在错误,欢迎留言交流。感谢你的反馈。
如果你觉得这篇文章对你有帮助,请在文章的左下角点个赞。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。