通过重写mousemove函数实现窗口的移动,但是在项目中不可能对每一个模块都进行函数重写,通过使用事件滤波器(eventfilter)来解决这个问题,在事件滤波器中判断事件类型,然后进行相应操作,窗口移动思想是当检测到事件为鼠标移动事件后通过move函数将窗口移动相应的dx和dy距离;窗口拉伸的思路是:仿照QSizeGrip类中源码的思想。先将窗口进行大小的改变,为了保持对边不变(即你移动某一个边时,另一个边要保持不变),将对边移动到原来的位置。
qgrip.h/
#ifndef QGRIP_H
#define QGRIP_H
#include
#include
#include
#include
QT_BEGIN_NAMESPACE
enum ResizeRegion
{
Default,
North,
NorthEast,
East,
SouthEast,
South,
SouthWest,
West,
NorthWest,
Arrow
};
enum EdgeStatus{
Eg_normal,
Eg_top,
Eg_left,
Eg_right,
Eg_bottom
};
class QGrip : public QWidget
{
Q_OBJECT
public:
QGrip(QWidget *parent);
~QGrip();
void updateTopLevelWidget();
ResizeRegion resizeregion;
QPoint p;
QPoint dragPos;
QRect r;
int d;
Qt::Corner m_corner;
Qt::Edge m_edge;
int resizeBorderWidth=10;
Qt::Corner corner(QWidget*q,QMouseEvent*qe) const;
Qt::Edge edge()const;
void hideWidget(QWidget*q,EdgeStatus es);//窗口隐藏
void showWidget(QWidget*q,EdgeStatus es);//窗口显示
EdgeStatus isDirection(QWidget *q);//判断窗口位置状态
protected:
void paintEvent(QWidget*o,QPaintEvent *event,Qt::Corner m_corner);
bool eventFilter(QObject *o, QEvent *e) Q_DECL_OVERRIDE;
void setResizeCursor(QWidget*w,ResizeRegion region);
ResizeRegion getResizeRegion(QWidget*w,QPoint clientPos);
private:
EdgeStatus m_edgeStatus;
int show_edgeWidth=8;
QPoint inialPos;
QPoint mousePos;
QPoint mousePos2;
};
QT_END_NAMESPACE
#endif // QGRIP_H
//////////////////
qgrip.cpp
#include"qgrip.h"
#include<QPainter>
#include<QStyle>
#include<QStyleOption>
#include
#include<QDesktopWidget>
#include<QLayout>
#include<QApplication>
#include
QWidget *qt_sizegrip_topLevelWidget(QWidget* w)
{
while (w && !w->isWindow() && w->windowType() != Qt::SubWindow)
w = w->parentWidget();
return w;
}
void QGrip::paintEvent(QWidget*o,QPaintEvent *event,Qt::Corner m_corner)
{
QPainter painter(o);
QStyleOptionSizeGrip opt;
opt.init(o);
opt.corner=m_corner;
style()->drawControl(QStyle::CE_SizeGrip, &opt, &painter, o);
}
bool QGrip::eventFilter(QObject *o, QEvent *e)
{
QRect availableGeometry;
QWidget*oo=static_cast<QWidget*>(o);
QMouseEvent*ee=static_cast<QMouseEvent*>(e);
QPaintEvent*qp=static_cast<QPaintEvent*>(e);
m_edgeStatus=isDirection(oo);
if(ee->type()==QEvent::Leave){
hideWidget(oo,m_edgeStatus);
}
if(ee->type()==QEvent::Enter){
showWidget(oo,m_edgeStatus);
}
// if(ee->type()==QEvent::Move){
// QDesktopWidget*deskwidget=QApplication::desktop();
// if(oo->pos().x()>(-oo->frameGeometry().width()/2)&&(oo->pos().x()<(deskwidget->width()-oo->frameGeometry().width()/2))&&(oo->pos().y()>(-oo->frameGeometry().height()/2))){
// inialPos.rx()=oo->pos().x();
// inialPos.ry()=oo->pos().y();
// }
// }
if (e->type()==QEvent::MouseButtonPress&&ee->button() == Qt::LeftButton){//左键按下
this->p=ee->globalPos();//p获得整体坐标
this->r=oo->geometry();//r获得矩形坐标(包括宽高和x、y)
this->dragPos=ee->pos();//ee获得光标点击处的位置
resizeregion = getResizeRegion(oo,dragPos);//获得光标要移动的方向
setResizeCursor(oo,resizeregion);//将光标变为对应的箭头
}
if(e->type()==QEvent::MouseMove){//光标移动
QWidget*tlw=qt_sizegrip_topLevelWidget(oo);//定位到顶级窗口
QPoint np(ee->globalPos());//np储存光标移动后的整体坐标
QPoint clientCursorPos=ee->pos();//光标移动后的相对窗体的坐标
QRect qr=oo->rect();
QSize ns;
QRect resizeInnerRect(resizeBorderWidth, resizeBorderWidth, r.width() - 2*resizeBorderWidth, r.height() - 2*resizeBorderWidth);//判断是否移动
if(qr.contains(clientCursorPos) && resizeInnerRect.contains(clientCursorPos)){//属于移动
if ((ee->buttons() & Qt::LeftButton)) {
oo->move(ee->globalPos() - dragPos);
}
}
else{
if(resizeregion==NorthWest||resizeregion==NorthEast){ns.rheight()=r.height()-(np.y()-p.y());}//设置角
else if(resizeregion==SouthWest||resizeregion==SouthEast){ns.rheight()=r.height()+(np.y()-p.y());}
if(resizeregion==NorthWest||resizeregion==SouthWest){ns.rwidth()=r.width()-(np.x()-p.x());}
else if(resizeregion==NorthEast||resizeregion==SouthEast){ns.rwidth()=r.width()+(np.x()-p.x());}
else if(resizeregion==North){ns.rheight()=r.height()-(np.y()-p.y());ns.rwidth()=r.width();}//设置边
else if(resizeregion==South){ns.rheight()=r.height()+(np.y()-p.y());ns.rwidth()=r.width();}
else if(resizeregion==West){ns.rwidth()=r.width()-(np.x()-p.x());ns.rheight()=r.height();}
else if(resizeregion==East){ns.rwidth()=r.width()+(np.x()-p.x());ns.rheight()=r.height();}
ns = QLayout::closestAcceptableSize(tlw, ns);
QPoint p;
QRect nr(p, ns);
if(resizeregion==NorthWest){nr.moveBottomRight(r.bottomRight());}//设置角
if(resizeregion==NorthEast){nr.moveBottomLeft(r.bottomLeft());}
if(resizeregion==SouthWest){nr.moveTopRight(r.topRight());}
if(resizeregion==SouthEast){nr.moveTopLeft(r.topLeft());}
if(resizeregion==North){nr.moveBottom(r.bottom());nr.moveBottomRight(r.bottomRight());nr.moveBottomLeft(r.bottomLeft());}//设置边
if(resizeregion==South){nr.moveTop(r.top());nr.moveTopRight(r.topRight());nr.moveTopLeft(r.topLeft());}
if(resizeregion==West){nr.moveRight(r.right());nr.moveBottomRight(r.bottomRight());nr.moveTopRight(r.topRight());}
if(resizeregion==East){nr.moveLeft(r.left());nr.moveBottomLeft(r.bottomLeft());nr.moveTopLeft(r.topLeft());}
tlw->setGeometry(nr);
}
}
// else if(qr.contains(clientCursorPos) && resizeInnerRect.contains(clientCursorPos)){
// }
if (e->type()==QEvent::MouseButtonRelease){
oo->setCursor(Qt::ArrowCursor);
}//鼠标松开
}
void QGrip::setResizeCursor(QWidget *w, ResizeRegion region)
{
switch (region)
{
case North:
case South:
w->setCursor(Qt::SizeVerCursor);//设置光标为垂直双箭头
break;
case East:
case West:
w->setCursor(Qt::SizeHorCursor);
break;
case NorthWest:
case SouthEast:
w->setCursor(Qt::SizeFDiagCursor);
break;
case NorthEast:
case SouthWest:
w->setCursor(Qt::SizeBDiagCursor);
break;
case Arrow:
w->setCursor(Qt::ArrowCursor);
break;
default:
w->setCursor(Qt::ArrowCursor);
break;
}
}
ResizeRegion QGrip::getResizeRegion(QWidget *w, QPoint clientPos)
{
if (clientPos.y() <= resizeBorderWidth) {
if (clientPos.x() <= resizeBorderWidth){
return NorthWest;}
else if (clientPos.x() >= (w->width() - resizeBorderWidth))
return NorthEast;
else
return North;
}
else if (clientPos.y() >=(w->height() - resizeBorderWidth)) {
if (clientPos.x() <= resizeBorderWidth)
return SouthWest;
else if (clientPos.x() >= (w->width() - resizeBorderWidth))
return SouthEast;
else
return South;
}
else if (clientPos.x() <= resizeBorderWidth)
return West;
else if(clientPos.x() >=(w->width() - resizeBorderWidth))
return East;
else
return Arrow;
}
EdgeStatus QGrip::isDirection(QWidget *q)
{
QDesktopWidget*deskwidget=QApplication::desktop();
if(q->pos().y()<=show_edgeWidth) return Eg_top;
else if(q->pos().x()<=show_edgeWidth) return Eg_left;
else if(q->pos().x()>=(deskwidget->width()-q->frameGeometry().width()-show_edgeWidth)) return Eg_right;
else
return Eg_normal;
}
void QGrip::hideWidget(QWidget*q,EdgeStatus es)
{
QDesktopWidget*deskwidget=QApplication::desktop();
if(es==Eg_top){inialPos.rx()=q->pos().x(); inialPos.ry()=q->pos().y();Sleep(3*1000);q->move(q->pos().x(),show_edgeWidth-q->frameGeometry().height());}
else if(es==Eg_left){inialPos.rx()=q->pos().x(); inialPos.ry()=q->pos().y();Sleep(3*1000);q->move(show_edgeWidth-q->frameGeometry().width(),q->pos().y());}
else if(es==Eg_right){inialPos.rx()=q->pos().x(); inialPos.ry()=q->pos().y();Sleep(3*1000);q->move(deskwidget->width()-show_edgeWidth,q->pos().y());}
else
es==Eg_normal;
}
void QGrip::showWidget(QWidget *q,EdgeStatus es){
if(es==Eg_top){q->move(inialPos.x(),inialPos.y());}
else if(es==Eg_left){q->move(inialPos.x(),inialPos.y());}
else if(es==Eg_right){q->move(inialPos.x(),inialPos.y());}
}
QGrip::QGrip(QWidget *parent):QWidget(parent){m_edgeStatus=Eg_normal;}
QGrip::~QGrip(){}
/////////////////
widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include"qgrip.h"
#include<QSizeGrip>
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
this->setWindowFlags(Qt::FramelessWindowHint);
// QSizeGrip*q=new QSizeGrip(this);
QGrip*q=new QGrip(this);
this->installEventFilter(q);
}
Widget::~Widget()
{
delete ui;
}