Qt实现无边框窗口的示例代码

 更新时间:2024年01月07日 09:38:57   作者:小宇宙Zz  
本文主要介绍了Qt实现无边框窗口的示例代码,主要包括鼠标光标在不同区域的变化,关闭拖动窗口,窗口支持任意拉伸等,具有一定的参考价值,感兴趣的可以了解一下

创建无边框窗口

在构造函数内实现:

    //最小宽高
    this->setMinimumWidth(500);
    this->setMinimumHeight(300);
    //消除窗口边框
    setWindowFlags(Qt::FramelessWindowHint | Qt::WindowSystemMenuHint);
    //设置背景色
    this->setStyleSheet("background-color:#303030");
    //创建两个按钮
    btn1=new QPushButton(this);
    btn2=new QPushButton(this);
    btn1->setText("确认");
    btn2->setText("取消");
    btn1->setStyleSheet(R"(QPushButton {
            background-color: rgb(64, 64, 64);
            color:rgb(200,200,200);
            border: 1px solid #707070;
            border-radius: 5px;
            padding: 5px;
        })");
    btn2->setStyleSheet(R"(QPushButton {
            background-color: rgb(64, 64, 64);
            color:rgb(200,200,200);
            border: 1px solid #707070;
            border-radius: 5px;
            padding: 5px;
        })");
    QHBoxLayout* hor=new QHBoxLayout(this);
    hor->setSpacing(0);
    hor->setContentsMargins(10,10,10,10);
    hor->addWidget(btn1);
    hor->addWidget(btn2);
    //用于判断鼠标左键是否按下
     isleftpressed=false;
    //消除窗口边框
    setWindowFlags(Qt::FramelessWindowHint | Qt::WindowSystemMenuHint);

在这里先将基本的窗口呈现出来。

窗口区域的划分

在头文件加入鼠标事件

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

设定枚举,将窗口分为9个区域

enum Location {
    TOP,
    BOTTOM,
    LEFT,
    RIGHT,
    TOP_LEFT,
    TOP_RIGHT,
    BOTTOM_LEFT,
    BOTTOM_RIGHT,
    CENTER
};

 鼠标光标在不同区域的变化

在一个窗口里,(0,0)是窗口的最左上角,往右或者是往下坐标都会变大。

在这里实现鼠标在窗口的八个方向的变化。

并放入鼠标移动事件,用于判断鼠标位置(location).

    #define padding 10
    QRect rect=this->rect();
    //将坐标转化为相对于整个屏幕的坐标
    QPoint topleft=mapToGlobal(rect.topLeft());
    QPoint bottomright=mapToGlobal(rect.bottomRight());
    int x=globalpos.x();
    int y=globalpos.y();
    //鼠标位于左上角
    if(x>topleft.x()&&x<topleft.x()+padding&&y>topleft.y()&&y<topleft.y()+padding)
    {
        location=TOP_LEFT;
        //这里鼠标光标变化
        this->setCursor(QCursor(Qt::SizeFDiagCursor));
    }
    //鼠标位于左下角
    else if(x>topleft.x()&&x<topleft.x()+padding&&y<bottomright.y()&&y>bottomright.y()-padding)
    {
        location=BOTTOM_LEFT;
        this->setCursor(QCursor(Qt::SizeBDiagCursor));
    }
    //鼠标位于右上角
   else if(x<bottomright.x()&&x>bottomright.x()-padding&&y>topleft.y()&&y<topleft.y()+padding)
    {
        location=TOP_RIGHT;
        this->setCursor(QCursor(Qt::SizeBDiagCursor));
    }
    //鼠标位于右下角
    else if(x<bottomright.x()&&x>bottomright.x()-padding&&y>bottomright.y()-padding&&y<bottomright.y())
    {
        location=BOTTOM_RIGHT;
        this->setCursor(Qt::SizeFDiagCursor);
    }
    //鼠标位于上面
    else if(y>topleft.y()&&y<topleft.y()+padding)
    {
        location=TOP;
        this->setCursor(Qt::SizeVerCursor);

    }
    //鼠标位于左边
    else if(x>topleft.x()&&x<topleft.x()+padding)
    {
        location=LEFT;
        this->setCursor(Qt::SizeHorCursor);
    }
    //鼠标位于下面
    else if(y>bottomright.y()-padding&&y<bottomright.y())
    {
        location=BOTTOM;
        this->setCursor(Qt::SizeVerCursor);
    }
    //鼠标位于右边
    else if(x<bottomright.x()&&x>bottomright.x()-padding)
    {
        location=RIGHT;
        this->setCursor(Qt::SizeHorCursor);
    }
        //鼠标位于中间
    else
    {
        location=CENTER;
        this->setCursor(QCursor(Qt::ArrowCursor));
    }

将其封装成函数,加入鼠标移动事件。 

右键关闭窗口

窗口边框消除后,右上角的叉叉也随之消失,于是我们加入一个右键关闭窗口的功能。

先前已经在头文件中加入了三个鼠标事件,现在来实现其中的按下事件

void Widget::mousePressEvent(QMouseEvent* event)
{
    switch (event->button())
    {
        //右键关闭窗口
    case Qt::RightButton:
        this->close();
        break;
    default:
        break;
    }
}

中间区域拖动窗口

在这里,需要记录鼠标的实时位置,并将窗口实时移动。

所以我们需要实时触发鼠标移动事件,并启用鼠标追踪。

this->setMouseTracking(true);

接下来实现修正鼠标按下和移动事件

void Widget::mousePressEvent(QMouseEvent* event)
{
    switch (event->button())
    {
        //右键关闭窗口
    case Qt::RightButton:
        this->close();
        break;
        //记录鼠标按下时位置与窗口左上角的距离
    case Qt::LeftButton:
        //用于判断左键是否按下
        isleftpressed=true;
        if(location==CENTER)
        mousepos=event->globalPos()-this->frameGeometry().topLeft();
    default:
        break;
    }
}

窗口要移动到的新位置即是原窗口位置加上鼠标移动的位置。

鼠标移动时,实时触发。

void Widget::mouseMoveEvent(QMouseEvent *event)
{
    //这里是之前鼠标光标变化的函数
    if(!isleftpressed)
    {
        this->setcursorshape(globalpos);
        return;
    }
    //中间位置拖动窗口
    if(location==CENTER&&isleftpressed)
    {
        move(event->globalPos()-mousepos);
        event->accept();
        return;
    }



}

鼠标在不同方向对窗口的拉伸

在这里实现鼠标在边缘八个方向按下拉动时,窗口的变形。

即鼠标左键按下,触发鼠标移动事件时触发。

void Widget::mouseMoveEvent(QMouseEvent *event)
{
    //记录鼠标当前位置
    QPoint globalpos=event->globalPos();
    QRect rect=this->rect();
    QPoint topleft=mapToGlobal(rect.topLeft());
    QPoint bottomright=mapToGlobal(rect.bottomRight());
    //创建一个矩形,并拉伸,最后设置其为窗口
    QRect rmove(topleft,bottomright);
    switch (location)
    {
    case TOP:
        //这里的if防止最小后窗口整体向下移动
        if(bottomright.y()-globalpos.y()>this->minimumHeight())
        rmove.setY(globalpos.y());
        break;
    case   BOTTOM:
        rmove.setHeight(globalpos.y()-topleft.y());
        break;
    case LEFT:
        if(bottomright.x()-globalpos.x()>this->minimumWidth())
        rmove.setX(globalpos.x());
        break;
    case RIGHT:
        rmove.setWidth(globalpos.x()-topleft.x());
        break;
    case TOP_LEFT:
        if(bottomright.y()-globalpos.y()>this->minimumHeight()&&bottomright.x()-globalpos.x()>this->width())
        {
             rmove.setY(globalpos.y());
            rmove.setX(globalpos.x());
        }
        break;
    case TOP_RIGHT:
        if(bottomright.y()-globalpos.y()>this->minimumHeight())
        {
            rmove.setY(globalpos.y());
            rmove.setWidth(globalpos.x()-topleft.x());
        }
        break;
    case BOTTOM_LEFT:
         if(bottomright.x()-globalpos.x()>this->width())
        {
            rmove.setHeight(globalpos.y()-topleft.y());
                    rmove.setX(globalpos.x());
        }
         break;
    case BOTTOM_RIGHT:
         rmove.setHeight(globalpos.y()-topleft.y());
         rmove.setWidth(globalpos.x()-topleft.x());
         break;
    case CENTER:
         break;
    }
    //重新设置窗口几何形状
    this->setGeometry(rmove);
        return;

}

需要注意的是在拖动顶部时,只需更新窗口的 Y 坐标,以实现向下拖动的效果。在拖动底部时,更新窗口的高度,以实现向上或向下调整大小的效果。这两种情况之所以有不同的处理方式,是因为拖动顶部只需要改变 Y 坐标,而拖动底部则需要改变高度。同样的逻辑也适用于左、右、左上、右上、左下、右下等不同的边界位置,因为每个位置的操作影响的窗口属性是不同的。

到此这篇关于Qt实现无边框窗口的示例代码的文章就介绍到这了,更多相关Qt 无边框窗口内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 通过c语言调用系统curl动态库的示例详解

    通过c语言调用系统curl动态库的示例详解

    这篇文章中我们将通过一个简单的示例来讲解如何在Ubuntu系统中通过C语言调用动态库(共享库)的方法,我们将使用libcurl库,这是一个基于客户端的URL传输库,广泛用于各种程序和应用中以访问网页和服务器数据,需要的朋友可以参考下
    2024-03-03
  • 详解散列表算法与其相关的C语言实现

    详解散列表算法与其相关的C语言实现

    这篇文章主要介绍了详解散列表算法与其相关的C语言实现,平时经常出现于各大考试竞赛与程序员面试题目当中,需要的朋友可以参考下
    2015-08-08
  • C语言合并两个带头节点升序排列链表

    C语言合并两个带头节点升序排列链表

    这篇文章主要为大家详细介绍了C语言合并两个带头节点升序排列链表的方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-03-03
  • C++ 中国象棋的实现流程详解

    C++ 中国象棋的实现流程详解

    中国象棋是起源于中国的一种棋,属于二人对抗性游戏的一种,在中国有着悠久的历史。由于用具简单,趣味性强,成为流行极为广泛的棋艺活动
    2021-11-11
  • c语言实现从源文件从文本到可执行文件经历的过程

    c语言实现从源文件从文本到可执行文件经历的过程

    这篇文章主要介绍了c语言实现从源文件从文本到可执行文件经历的过程,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-07-07
  • 关于背包问题的一些理解和应用

    关于背包问题的一些理解和应用

    这篇文章主要介绍了关于背包问题的一些理解和应用,本文可以说是背包问题九讲的补充、读后感,需要的朋友可以参考下
    2014-08-08
  • C语言实现BMP格式图片转化为灰度

    C语言实现BMP格式图片转化为灰度

    这篇文章主要为大家详细介绍了C语言实现BMP格式图片转化为灰度,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-10-10
  • 一文详解C++中的类型转化

    一文详解C++中的类型转化

    说起类型转化,我们在C语言之前的学习中可以了解到,类型转换可以分为两种情况:隐式类型转化;显示类型转化。但是为什么在c++中还要继续对类型转化做文章呢?我们一起来看
    2023-04-04
  • 探讨编写int strlen(char *strDest);不允许定义变量的问题

    探讨编写int strlen(char *strDest);不允许定义变量的问题

    本篇文章是对编写int strlen(char *strDest);不允许定义变量的问题进行了详细的分析介绍,需要的朋友参考下
    2013-05-05
  • Dijkstra最短路径算法实现代码

    Dijkstra最短路径算法实现代码

    这篇文章主要介绍了Dijkstra最短路径算法实现代码,有需要的朋友可以参考一下
    2013-12-12

最新评论