当前位置: 首页 > news >正文

QT去除窗口边框(无边框)

ch21_TencentMeetingLogin::ch21_TencentMeetingLogin(QWidget *parent): QDialog(parent)
{ui.setupUi(this);this->setWindowFlags(Qt::FramelessWindowHint);//去除窗口边框
}

但此时窗口不能拖动且点击任务栏程序图标不能最小化!

 this->setWindowFlags(Qt::FramelessWindowHint | Qt::WindowMinMaxButtonsHint);

上面代码设置Qt框架中窗口的属性。具体来说,它调用了一个窗口对象(假设为this指针所指向的对象)的setWindowFlags方法,以设置该窗口的标志(Flags)。这里设置的标志有两个:Qt::FramelessWindowHintQt::WindowMinMaxButtonsHint

  • Qt::FramelessWindowHint:这个标志用于创建一个无边框的窗口。通常,窗口会有一个默认的边框,包括标题栏、边缘等。设置了这个标志后,窗口将不再显示这些元素,使得窗口可以自定义外观。

  • Qt::WindowMinMaxButtonsHint:这个标志用于在窗口的标题栏上显示最小化(Min)和最大化(Max)按钮。在设置无边框后,Qt::WindowMinMaxButtonsHint可能不会生效,因为无边框窗口通常不会有标题栏,也就没有最小化等按钮,从而也无法显示这些按钮。所以我们需要手动设置!

当你在Qt中设置一个窗口为无边框(Qt::FramelessWindowHint)时,窗口通常会失去默认的拖动和大小调整功能,因为这些功能通常依赖于窗口的边框和标题栏。就像Qt::WindowMinMaxButtonsHint 标志可能不会在无边框窗口中生效,因为它依赖于标题栏来显示最小化和最大化按钮。

如何实现窗口移动

去掉窗口边框后,窗口无法移动,如何让窗口动起来呢?

重写鼠标按下,移动的事件

protected:void mouseMoveEvent(QMouseEvent *event) override;void mousePressEvent(QMouseEvent *event) override;

注意相对位置和绝对位置:

窗口位置:this->pos()窗口左上角相对于桌面左上角        

鼠标位置:event->pos()是鼠标相对于应用程序的位置,相对位置

                  event->globalPos()相对于桌面原点的位置,绝对位置

private:QPoint diff_pos;//鼠标和窗口位置的距离QPoint window_pos;//鼠标位置QPoint mouse_pos;//窗口位置
void Widget::mousePressEvent(QMouseEvent *event)
{mouse_pos = event->globalPos();//鼠标绝对位置window_pos = this->pos();//窗口绝对位置diff_pos = mouse_pos - window_pos;//距离差
}void Widget::mouseMoveEvent(QMouseEvent *event)
{QPoint pos = event->globalPos();//此时鼠标的位置this->move(pos-diff_pos);//计算窗口的位置在哪里}

自定义标题栏并实现拖拽拉伸

去掉窗口边框后,没有标题栏,需要自定义标题栏。创建标题栏界面类,添加到界面上,并添加最小化,最大化,关闭按钮。

创建标题栏类CTitleBar

头文件

#ifndef CTITLEBAR_H
#define CTITLEBAR_H#include <QWidget>
#include <QLabel>
#include <QPushButton>
class CTitleBar : public QWidget//所有的窗口都需要QWidget
{Q_OBJECT
public:explicit CTitleBar(QObject *parent = nullptr);~CTitleBar();
private://m表示成员函数,p表示指针QLabel *m_pLogo;QLabel *m_ptitleTextLabel;QPushButton *m_pSetBtn;QPushButton *m_pMinBtn;QPushButton *m_pMaxBtn;QPushButton *m_pCloseBtn;private:void initUI();//UI初始化
};#endif // CTITLEBAR_H

cpp

#include "ctitlebar.h"
#include <QHBoxLayout>
CTitleBar::CTitleBar(QObject *parent)
{initUI();
}CTitleBar::~CTitleBar()
{}void CTitleBar::initUI()
{//禁止父窗口影响子窗口的样式setAttribute(Qt::WA_StyledBackground);this->setFixedHeight(32+5*2);//32+上下距离this->setStyleSheet("background-color:rgb(155,155,155)");m_pLogo = new QLabel(this);m_pLogo->setFixedSize(32,32);m_pLogo->setText("logo");m_ptitleTextLabel = new QLabel(this);m_ptitleTextLabel->setText("我是标题");m_ptitleTextLabel->setFixedWidth(120);m_pSetBtn = new QPushButton(this);m_pSetBtn->setFixedSize(32,32);m_pMinBtn = new QPushButton(this);m_pMinBtn->setFixedSize(32,32);m_pMaxBtn = new QPushButton(this);m_pMaxBtn->setFixedSize(32,32);m_pCloseBtn = new QPushButton(this);m_pCloseBtn->setFixedSize(32,32);QHBoxLayout *pHlay = new QHBoxLayout(this);pHlay->addWidget(m_pLogo);pHlay->addWidget(m_ptitleTextLabel);pHlay->addStretch();//加弹簧pHlay->addWidget(m_pSetBtn);pHlay->addWidget(m_pMinBtn);pHlay->addWidget(m_pMaxBtn);pHlay->addWidget(m_pCloseBtn);pHlay->setContentsMargins(5,5,5,5);
}

widget.h

private:void initUI();CTitleBar *m_pTitleBar = nullptr;//标题栏

widget.cpp

void Widget::initUI()
{m_pTitleBar = new CTitleBar(this);QWidget *w = new QWidget(this);w->setMinimumSize(800,600);QVBoxLayout *pVlay = new QVBoxLayout(this);pVlay->addWidget(m_pTitleBar);pVlay->addWidget(w);pVlay->setContentsMargins(0,0,0,0);
}

一个很有用的Qt属性:

    //禁止父窗口影响子窗口的样式setAttribute(Qt::WA_StyledBackground);

无边框窗口拖拽移动另外一种的方法

#include <qt_windows.h>
void CTitleBar::mousePressEvent(QMouseEvent *event)
{if(ReleaseCapture()){QWidget *pWindow = this->window();if(pWindow->isTopLevel()){SendMessage(HWND(pWindow->winId()),WM_SYSCOMMAND,SC_MOVE+HTCAPTION,0);}}
}

这段代码的目的是允许用户通过点击自定义的标题栏来移动整个窗口。它通过释放鼠标捕获、获取顶级窗口句柄,并发送一个模拟点击标题栏的系统命令消息来实现这一功能。

ReleaseCapture()是一个Windows API函数,用于释放当前窗口的鼠标捕获。在Windows系统中,如果一个窗口捕获了鼠标,那么所有的鼠标输入都会发送到那个窗口,直到捕获被释放。在这里,它的目的是确保可以移动窗口,即使鼠标最初不是在这个窗口上按下的。如果ReleaseCapture()调用成功,它会返回非零值(在Windows中通常表示成功),函数继续执行内部的代码块。

QWidget *pWindow = this->window();: 这行代码获取CTitleBar所属的顶级窗口(即包含这个标题栏的窗口)。this->window()调用返回的是CTitleBar的直接或间接父窗口,且这个父窗口必须是顶级窗口(即没有父窗口的窗口,通常是应用程序的主窗口)。

if(pWindow->isTopLevel()){...}: 这行代码检查获取到的窗口是否是顶级窗口。这是必要的,因为只有顶级窗口才能被移动。

发送WM_SYSCOMMAND消息:

  • SendMessage(HWND(pWindow->winId()),WM_SYSCOMMAND,SC_MOVE+HTCAPTION,0);: 这行代码是Windows API的调用,用于发送一个系统命令消息(WM_SYSCOMMAND)到指定的窗口(在这里是pWindow)。WM_SYSCOMMAND消息用于执行系统命令,比如最小化、最大化、关闭窗口或移动窗口等。
  • HWND(pWindow->winId())将Qt的窗口句柄(winId()返回)转换为Windows的句柄类型(HWND)。
  • SC_MOVE+HTCAPTION是一个组合值,SC_MOVE表示移动窗口的命令,HTCAPTION是一个特殊的击中测试代码,表示标题栏区域。将这两个值相加,告诉系统像用户点击了标题栏一样移动窗口。
  • 最后一个参数0是额外的消息信息,对于WM_SYSCOMMANDSC_MOVE+HTCAPTION的组合来说,这个参数通常不需要。

这代码依赖于Windows特定的API,不适用于跨平台开发!

无边窗口的拉伸改变大小 

 

#include <qt_windows.h>

未完待续


http://www.mrgr.cn/news/78847.html

相关文章:

  • webGL入门教程_06变换矩阵与绕轴旋转总结
  • AI开发:逻辑回归 - 实战演练- 垃圾邮件的识别(二)
  • 医院管理系统
  • droppath
  • 洛谷 P1308 [NOIP2011 普及组] 统计单词数 C语言
  • 数据结构——排序算法第一幕(插入排序:直接插入排序、希尔排序 选择排序:直接选择排序,堆排序)超详细!!!!
  • Java中 HttpURLConnection 和 HttpClient 详解(初学者友好)
  • oracle中删除指定前缀的表
  • Web API基本认知
  • 胖AP和瘦AP的区别
  • C#基础教程
  • 理解字母形状,从而获得含义
  • 【Linux】常用命令二
  • 【实验13】使用预训练ResNet18进行CIFAR10分类
  • Docker基础使用
  • 【MySQL — 数据库基础】MySQL的安装与配置 & 数据库简单介绍
  • LearnOpenGL学习(光照 -- 颜色,基础光照,材质,光照贴图)
  • 数据结构之三:栈和队列
  • Web登录页面设计
  • 用go语言写一个小服务
  • 手机卡限速丨中国移动5G变3G,网速500kb
  • 单链表---移除链表元素
  • LearnOpenGL学习(光照 -- 颜色,基础光照,材质)
  • go使用mysql实现增删改查操作
  • 我们来学mysql -- 事务之概念(原理篇)
  • 深度学习 | pytorch + torchvision + python 版本对应及环境安装