zoukankan      html  css  js  c++  java
  • Qt开源作品16-通用无边框拖动拉伸

    一、前言

    相信各位CS结构开发的程序员,多多少少都遇到过需要美化界面的事情,一般都不会采用系统的标题栏,这样就需要无边框标题栏窗体,默认的话无边框的标题栏都不支持拉伸和拖动的,毕竟去掉了标题栏则意味着失去了系统的窗体的属性,拉伸和拖动都需要自己写代码去实现,网上有很多类似的开源的方案,我也看过不少,总体来说复杂了些,对于初学者来说有可能看的云里雾里的,比如边框四周八个方位都可以自由拉伸这块,我的思路是针对设定的八个方位的区域进行识别鼠标是否按下,按下的哪个部位则执行什么拉伸策略,鼠标移到哪个位置则对应改变鼠标指针形状,更浅显易懂一些,至于拖动移动,还可以设置拖动的标题栏的高度等。

    主要功能:

    1. 可以指定需要无边框的widget
    2. 边框四周八个方位都可以自由拉伸
    3. 可设置对应位置的边距,以便识别更大区域
    4. 可设置是否允许拖动
    5. 可设置是否允许拉伸

    二、代码思路

    bool FramelessWidget::eventFilter(QObject *watched, QEvent *event)
    {
        if (widget != 0 && watched == widget) {
            if (event->type() == QEvent::Resize) {
                //重新计算八个描点的区域,描点区域的作用还有就是计算鼠标坐标是否在某一个区域内
                int width = widget->width();
                int height = widget->height();
    
                //左侧描点区域
                rectLeft = QRect(0, padding, padding, height - padding * 2);
                //上侧描点区域
                rectTop = QRect(padding, 0, width - padding * 2, padding);
                //右侧描点区域
                rectRight = QRect(width - padding, padding, padding, height - padding * 2);
                //下侧描点区域
                rectBottom = QRect(padding, height - padding, width - padding * 2, padding);
    
                //左上角描点区域
                rectLeftTop = QRect(0, 0, padding, padding);
                //右上角描点区域
                rectRightTop = QRect(width - padding, 0, padding, padding);
                //左下角描点区域
                rectLeftBottom = QRect(0, height - padding, padding, padding);
                //右下角描点区域
                rectRightBottom = QRect(width - padding, height - padding, padding, padding);
            } else if (event->type() == QEvent::HoverMove) {
                //设置对应鼠标形状,这个必须放在这里而不是下面,因为可以在鼠标没有按下的时候识别
                QHoverEvent *hoverEvent = (QHoverEvent *)event;
                QPoint point = hoverEvent->pos();
                if (resizeEnable) {
                    if (rectLeft.contains(point)) {
                        widget->setCursor(Qt::SizeHorCursor);
                    } else if (rectRight.contains(point)) {
                        widget->setCursor(Qt::SizeHorCursor);
                    } else if (rectTop.contains(point)) {
                        widget->setCursor(Qt::SizeVerCursor);
                    } else if (rectBottom.contains(point)) {
                        widget->setCursor(Qt::SizeVerCursor);
                    } else if (rectLeftTop.contains(point)) {
                        widget->setCursor(Qt::SizeFDiagCursor);
                    } else if (rectRightTop.contains(point)) {
                        widget->setCursor(Qt::SizeBDiagCursor);
                    } else if (rectLeftBottom.contains(point)) {
                        widget->setCursor(Qt::SizeBDiagCursor);
                    } else if (rectRightBottom.contains(point)) {
                        widget->setCursor(Qt::SizeFDiagCursor);
                    } else {
                        widget->setCursor(Qt::ArrowCursor);
                    }
                }
    
                //根据当前鼠标位置,计算XY轴移动了多少
                int offsetX = point.x() - lastPos.x();
                int offsetY = point.y() - lastPos.y();
    
                //根据按下处的位置判断是否是移动控件还是拉伸控件
                if (moveEnable) {
                    if (pressed) {
                        widget->move(widget->x() + offsetX, widget->y() + offsetY);
                    }
                }
    
                if (resizeEnable) {
                    if (pressedLeft) {
                        int resizeW = widget->width() - offsetX;
                        if (widget->minimumWidth() <= resizeW) {
                            widget->setGeometry(widget->x() + offsetX, rectY, resizeW, rectH);
                        }
                    } else if (pressedRight) {
                        widget->setGeometry(rectX, rectY, rectW + offsetX, rectH);
                    } else if (pressedTop) {
                        int resizeH = widget->height() - offsetY;
                        if (widget->minimumHeight() <= resizeH) {
                            widget->setGeometry(rectX, widget->y() + offsetY, rectW, resizeH);
                        }
                    } else if (pressedBottom) {
                        widget->setGeometry(rectX, rectY, rectW, rectH + offsetY);
                    } else if (pressedLeftTop) {
                        int resizeW = widget->width() - offsetX;
                        int resizeH = widget->height() - offsetY;
                        if (widget->minimumWidth() <= resizeW) {
                            widget->setGeometry(widget->x() + offsetX, widget->y(), resizeW, resizeH);
                        }
                        if (widget->minimumHeight() <= resizeH) {
                            widget->setGeometry(widget->x(), widget->y() + offsetY, resizeW, resizeH);
                        }
                    } else if (pressedRightTop) {
                        int resizeW = rectW + offsetX;
                        int resizeH = widget->height() - offsetY;
                        if (widget->minimumHeight() <= resizeH) {
                            widget->setGeometry(widget->x(), widget->y() + offsetY, resizeW, resizeH);
                        }
                    } else if (pressedLeftBottom) {
                        int resizeW = widget->width() - offsetX;
                        int resizeH = rectH + offsetY;
                        if (widget->minimumWidth() <= resizeW) {
                            widget->setGeometry(widget->x() + offsetX, widget->y(), resizeW, resizeH);
                        }
                        if (widget->minimumHeight() <= resizeH) {
                            widget->setGeometry(widget->x(), widget->y(), resizeW, resizeH);
                        }
                    } else if (pressedRightBottom) {
                        int resizeW = rectW + offsetX;
                        int resizeH = rectH + offsetY;
                        widget->setGeometry(widget->x(), widget->y(), resizeW, resizeH);
                    }
                }
            } else if (event->type() == QEvent::MouseButtonPress) {
                //记住当前控件坐标和宽高以及鼠标按下的坐标
                QMouseEvent *mouseEvent = (QMouseEvent *)event;
                rectX = widget->x();
                rectY = widget->y();
                rectW = widget->width();
                rectH = widget->height();
                lastPos = mouseEvent->pos();
    
                //判断按下的手柄的区域位置
                if (rectLeft.contains(lastPos)) {
                    pressedLeft = true;
                } else if (rectRight.contains(lastPos)) {
                    pressedRight = true;
                } else if (rectTop.contains(lastPos)) {
                    pressedTop = true;
                } else if (rectBottom.contains(lastPos)) {
                    pressedBottom = true;
                } else if (rectLeftTop.contains(lastPos)) {
                    pressedLeftTop = true;
                } else if (rectRightTop.contains(lastPos)) {
                    pressedRightTop = true;
                } else if (rectLeftBottom.contains(lastPos)) {
                    pressedLeftBottom = true;
                } else if (rectRightBottom.contains(lastPos)) {
                    pressedRightBottom = true;
                } else {
                    pressed = true;
                }
            } else if (event->type() == QEvent::MouseMove) {
                //改成用HoverMove识别
            } else if (event->type() == QEvent::MouseButtonRelease) {
                //恢复所有
                pressed = false;
                pressedLeft = false;
                pressedRight = false;
                pressedTop = false;
                pressedBottom = false;
                pressedLeftTop = false;
                pressedRightTop = false;
                pressedLeftBottom = false;
                pressedRightBottom = false;
                widget->setCursor(Qt::ArrowCursor);
            }
        }
    
        return QObject::eventFilter(watched, event);
    }
    

    三、效果图

    四、开源主页

    以上作品完整源码下载都在开源主页,会持续不断更新作品数量和质量,欢迎各位关注。

    1. 国内站点:https://gitee.com/feiyangqingyun/QWidgetDemo
    2. 国际站点:https://github.com/feiyangqingyun/QWidgetDemo
    3. 个人主页:https://blog.csdn.net/feiyangqingyun
    4. 知乎主页:https://www.zhihu.com/people/feiyangqingyun/
  • 相关阅读:
    【题解】【BT】【Leetcode】Populating Next Right Pointers in Each Node
    【题解】【BT】【Leetcode】Binary Tree Level Order Traversal
    【题解】【BST】【Leetcode】Unique Binary Search Trees
    【题解】【矩阵】【回溯】【Leetcode】Rotate Image
    【题解】【排列组合】【素数】【Leetcode】Unique Paths
    【题解】【矩阵】【回溯】【Leetcode】Unique Paths II
    【题解】【BST】【Leetcode】Validate Binary Search Tree
    【题解】【BST】【Leetcode】Convert Sorted Array to Binary Search Tree
    第 10 章 判断用户是否登录
    第 8 章 动态管理资源结合自定义登录页面
  • 原文地址:https://www.cnblogs.com/feiyangqingyun/p/12928368.html
Copyright © 2011-2022 走看看