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 无边框窗口内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • OpenCV实现直线拟合

    OpenCV实现直线拟合

    这篇文章主要为大家详细介绍了OpenCV实现直线拟合,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-06-06
  • Qt GUI图形图像开发之Qt表格控件QTableView简单使用方法及QTableView与QTableWidget区别

    Qt GUI图形图像开发之Qt表格控件QTableView简单使用方法及QTableView与QTableWidget区

    这篇文章主要介绍了Qt GUI图形图像开发之Qt表格控件QTableView简单使用方法,需要的朋友可以参考下
    2020-03-03
  • C++ Boost Conversion超详细讲解

    C++ Boost Conversion超详细讲解

    Boost是为C++语言标准库提供扩展的一些C++程序库的总称。Boost库是一个可移植、提供源代码的C++库,作为标准库的后备,是C++标准化进程的开发引擎之一,是为C++语言标准库提供扩展的一些C++程序库的总称
    2022-11-11
  • C语言中的分支循环其嵌套语句

    C语言中的分支循环其嵌套语句

    这篇文章主要介绍了C语言中的分支循环其嵌套语句,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-02-02
  • 利用OpenCV实现绿幕视频背景替换

    利用OpenCV实现绿幕视频背景替换

    这篇文章主要介绍了如何利用OpenCV实现绿幕视频背景替换功能,文中的示例代码讲解详细,对我们学习OpenCV有一定的帮助,感兴趣的可以学习一下
    2022-01-01
  • C语言修炼之路灵根孕育源流出 初识C言大道生上篇

    C语言修炼之路灵根孕育源流出 初识C言大道生上篇

    C语言是一门面向过程、抽象化的通用程序设计语言,广泛应用于底层开发。C语言能以简易的方式编译、处理低级存储器。C语言是仅产生少量的机器语言以及不需要任何运行环境支持便能运行的高效率程序设计语言
    2022-03-03
  • C++ 学习之旅三 我和超级玛丽有个约会

    C++ 学习之旅三 我和超级玛丽有个约会

    学习了c++有一周有余了吧,感谢孙鑫老师的视频教程,让我   对C++有了基本的了解,并理解到C++与.net 的许许多多的区别,更要感谢网民为programaking的人,会为我提供了超级玛丽制作揭秘 这套宝贵的教程,让我 做做出了这个项目,对c++ 有了一个更深层次的认识
    2012-11-11
  • QT .pro文件的实现

    QT .pro文件的实现

    本文主要介绍了QT .pro文件的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-01-01
  • Arduino控制舵机详解 附代码

    Arduino控制舵机详解 附代码

    rduino是一款便捷灵活、方便上手的开源电子原型平台,它构建于开放原始码simple I/O介面版,并且具有使用类似Java、C语言的Processing/Wiring开发环境,这篇文章主要介绍了Arduino控制舵机详解(含代码),需要的朋友可以参考下
    2023-05-05
  • FFRPC应用 Client/Server使用及原理解析

    FFRPC应用 Client/Server使用及原理解析

    这篇文章主要介绍了FFRPC应用 Client/Server使用及原理解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-08-08

最新评论