Qt 无边框窗体改变大小 完美实现

来源:互联网 发布:淘宝上祛痘产品可信吗 编辑:程序博客网 时间:2024/06/07 06:57


近期,做项目用到无边框窗体,令人蛋疼的是无边框窗体大小的改变要像右边框那样,上下左右四周,而且要流畅。

网上也找了些代码,发现居然还要连接到windows事件,这显然不合常理,后来自己新建了demo,写了一个小时,问题太多了,扔一边先不管了。

今天需要改进UI界面,没办法了,重新整理了下思路,没想到做出来了。下面来分享下实现的过程,也许是菜鸟专栏,高手勿喷~

1.首先大家要了解各九宫格的概念

一个窗体可以被划分为上、下、左、右、左上、左下、右上、右下、中间,除了中间部分,其他都需要写程序处理。

在程序中定义Padding 为2,并同时定义枚举类型。

#define PADDING 2
enum Direction { UP=0, DOWN=1, LEFT, RIGHT, LEFTTOP, LEFTBOTTOM, RIGHTBOTTOM, RIGHTTOP, NONE };

2.定义一个方法,参数为鼠标目前的全局位置。

void Dialog::region(const QPoint &cursorGlobalPoint){  // 获取窗体在屏幕上的位置区域,tl为topleft点,rb为rightbottom点    QRect rect = this->rect();    QPoint tl = mapToGlobal(rect.topLeft());    QPoint rb = mapToGlobal(rect.bottomRight());    int x = cursorGlobalPoint.x();    int y = cursorGlobalPoint.y();    if(tl.x() + PADDING >= x && tl.x() <= x && tl.y() + PADDING >= y && tl.y() <= y) {        // 左上角        dir = LEFTTOP;        this->setCursor(QCursor(Qt::SizeFDiagCursor));  // 设置鼠标形状    } else if(x >= rb.x() - PADDING && x <= rb.x() && y >= rb.y() - PADDING && y <= rb.y()) {        // 右下角        dir = RIGHTBOTTOM;        this->setCursor(QCursor(Qt::SizeFDiagCursor));    } else if(x <= tl.x() + PADDING && x >= tl.x() && y >= rb.y() - PADDING && y <= rb.y()) {        //左下角        dir = LEFTBOTTOM;        this->setCursor(QCursor(Qt::SizeBDiagCursor));    } else if(x <= rb.x() && x >= rb.x() - PADDING && y >= tl.y() && y <= tl.y() + PADDING) {        // 右上角        dir = RIGHTTOP;        this->setCursor(QCursor(Qt::SizeBDiagCursor));    } else if(x <= tl.x() + PADDING && x >= tl.x()) {        // 左边        dir = LEFT;        this->setCursor(QCursor(Qt::SizeHorCursor));    } else if( x <= rb.x() && x >= rb.x() - PADDING) {        // 右边        dir = RIGHT;        this->setCursor(QCursor(Qt::SizeHorCursor));    }else if(y >= tl.y() && y <= tl.y() + PADDING){        // 上边        dir = UP;        this->setCursor(QCursor(Qt::SizeVerCursor));    } else if(y <= rb.y() && y >= rb.y() - PADDING) {        // 下边        dir = DOWN;        this->setCursor(QCursor(Qt::SizeVerCursor));    }else {        // 默认        dir = NONE;        this->setCursor(QCursor(Qt::ArrowCursor));    }}

3.在对话框类中定义几个私有成员变量

bool isLeftPressDown;  // 判断左键是否按下QPoint dragPosition;   // 窗口移动拖动时需要记住的点 Direction dir;        // 窗口大小改变时,记录改变方向

编写对话框构造函数,初始化几个变量并做一些其他工作。

isLeftPressDown = false;this->dir = NONE;this->setMinimumHeight(100);this->setMinimumWidth(150);this->setWindowFlags(Qt::FramelessWindowHint|Qt::WindowSystemMenuHint); // 设置成无边框对话框this->setMouseTracking(true);                    // 追踪鼠标this->setStyleSheet("QDialog{background:url(:/bg_main.png)}"); // 设置样式背景色,可有可无

4.接着就要实现几个重要的重载事件了

void mouseReleaseEvent(QMouseEvent *event);void mouseMoveEvent(QMouseEvent *event);void mousePressEvent(QMouseEvent *event);

实现过程如下:

void Dialog::mouseReleaseEvent(QMouseEvent *event){    if(event->button() == Qt::LeftButton) {        isLeftPressDown = false;        if(dir != NONE) {            this->releaseMouse();            this->setCursor(QCursor(Qt::ArrowCursor));        }    }}void Dialog::mousePressEvent(QMouseEvent *event){    switch(event->button()) {    case Qt::LeftButton:        isLeftPressDown = true;        if(dir != NONE) {            this->mouseGrabber();        } else {            dragPosition = event->globalPos() - this->frameGeometry().topLeft();        }        break;    case Qt::RightButton:        this->close();        break;    default:        QDialog::mousePressEvent(event);    }}void Dialog::mouseMoveEvent(QMouseEvent *event){    QPoint gloPoint = event->globalPos();    QRect rect = this->rect();    QPoint tl = mapToGlobal(rect.topLeft());    QPoint rb = mapToGlobal(rect.bottomRight());    if(!isLeftPressDown) {        this->region(gloPoint);    } else {        if(dir != NONE) {            QRect rMove(tl, rb);            switch(dir) {            case LEFT:                if(rb.x() - gloPoint.x() <= this->minimumWidth())                    rMove.setX(tl.x());                else                    rMove.setX(gloPoint.x());                break;            case RIGHT:                rMove.setWidth(gloPoint.x() - tl.x());                break;            case UP:                if(rb.y() - gloPoint.y() <= this->minimumHeight())                    rMove.setY(tl.y());                else                    rMove.setY(gloPoint.y());                break;            case DOWN:                rMove.setHeight(gloPoint.y() - tl.y());                break;            case LEFTTOP:                if(rb.x() - gloPoint.x() <= this->minimumWidth())                    rMove.setX(tl.x());                else                    rMove.setX(gloPoint.x());                if(rb.y() - gloPoint.y() <= this->minimumHeight())                    rMove.setY(tl.y());                else                    rMove.setY(gloPoint.y());                break;            case RIGHTTOP:                rMove.setWidth(gloPoint.x() - tl.x());                rMove.setY(gloPoint.y());                break;            case LEFTBOTTOM:                rMove.setX(gloPoint.x());                rMove.setHeight(gloPoint.y() - tl.y());                break;            case RIGHTBOTTOM:                rMove.setWidth(gloPoint.x() - tl.x());                rMove.setHeight(gloPoint.y() - tl.y());                break;            default:                break;            }            this->setGeometry(rMove);        } else {            move(event->globalPos() - dragPosition);            event->accept();        }    }    QDialog::mouseMoveEvent(event);}

到此为止,一个无边框窗体拖动并且改变大小的功能就实现了,Run and debug it。

总结起来,这个算法其实并不复杂,就看有几个点能不能想到:

1)窗体矩形区域要转换成在屏幕上的区域,我采取的方式就是取TopLeft和RightBottom两个点来确定这个区域。

2)鼠标移动要去全局的坐标。

3)region函数中判断坐标区间,然后改变鼠标形状,这块很容易出错,如果你一下子就写出来,那我真的很佩服。


转载自:http://www.cnblogs.com/xufeiyang/p/3313104.html

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 给小孩上户口母亲是外国人怎么办 宝宝在学校不敢跟老师说话怎么办? 早教课上宝宝总爱乱跑怎么办? 20天大的宝宝4天不拉大便怎么办 还不会说话的小孩子脾气大怎么办 两岁的宝宝说话变的口吃怎么办 37周b超宝宝腿短怎么办 3岁的宝宝说话说不好怎么办 小儿说话晚的原因宝宝说话晚怎么办 22岁的儿子在家不说话怎么办 儿子2周4个月了不说话怎么办 三岁的宝宝还不会数数怎么办 2岁宝宝晚上不睡觉不听话怎么办 8个月的狗狗怕人不敢出门怎么办 狗太怕人了怎么办都不敢出门 媳妇和婆婆晚上都不想带孩子怎么办 婆婆和媳妇带孩子观念不一样怎么办 婆婆给媳妇买了不喜欢的家具怎么办 断奶后宝宝对奶粉很抗拒怎么办 两岁宝宝断奶不喝奶粉怎么办 宝宝两岁了断奶后奶粉不吃怎么办 宝宝断奶两天了不愿意吃奶粉怎么办 一岁四个月宝宝断奶不喝奶粉怎么办 四个月宝宝断奶不喝奶粉怎么办 四个月宝宝断奶后不吃奶粉怎么办 2岁的宝宝不开口说话怎么办 一周岁宝宝断奶不喝奶粉怎么办 八个月宝宝断奶不喝奶粉怎么办 婆家人总是用心机对待娘家人怎么办 婆婆老是背后说我娘家人坏话怎么办 婆家姐带孩子住娘家不走怎么办? 老是想在娘家不想回婆家怎么办 娘家和婆家同时向我借钱怎么办 土地确权后娘家婆家都没有怎么办 结了婚婆家向娘家借钱怎么办? 婆婆的娘家人从我家住怎么办 八个月宝宝断奶后不吃奶粉怎么办 吃母乳的宝宝不吸奶嘴怎么办 宝宝吸了奶嘴不吸母乳怎么办 婴儿吃了奶嘴不吸母乳怎么办 十一个月宝宝断奶不喝奶粉怎么办