Qt 自定义无标题栏窗口:FramelessWidget 实现与解析

文章目录

    • 一、核心功能概览
    • 二、代码核心模块解析
      • [2.1 类结构与成员变量](#2.1 类结构与成员变量)
      • [2.2 构造函数:无标题栏初始化](#2.2 构造函数:无标题栏初始化)
      • [2.3 鼠标事件处理:拖拽与 Resize](#2.3 鼠标事件处理:拖拽与 Resize)
        • [2.3.1 鼠标按下事件(mousePressEvent)](#2.3.1 鼠标按下事件(mousePressEvent))
        • [2.3.2 鼠标移动事件(mouseMoveEvent)](#2.3.2 鼠标移动事件(mouseMoveEvent))
        • [2.3.3 鼠标释放事件(mouseReleaseEvent)](#2.3.3 鼠标释放事件(mouseReleaseEvent))
      • [2.4 光标形状更新(updateCursorShape)](#2.4 光标形状更新(updateCursorShape))
      • [2.5 窗口大小调整(handleResize)](#2.5 窗口大小调整(handleResize))
      • [2.6 全屏切换与状态记忆](#2.6 全屏切换与状态记忆)
        • [2.6.1 双击切换全屏(mouseDoubleClickEvent)](#2.6.1 双击切换全屏(mouseDoubleClickEvent))
        • [2.6.2 状态记忆(changeEvent)](#2.6.2 状态记忆(changeEvent))
      • [2.7 事件过滤器(eventFilter)](#2.7 事件过滤器(eventFilter))
    • 三、使用示例
    • 四、源码

在 Qt 开发中,默认窗口的标题栏样式往往难以满足个性化 UI 需求。无论是桌面应用的品牌化设计,还是特定场景下的交互优化,自定义无标题栏窗口都是常见需求。本文将基于一份完整的 FramelessWidget 实现代码,详细解析无标题栏窗口的核心技术点,包括窗口拖拽、边缘调整大小、全屏切换等功能,帮助开发者快速掌握自定义窗口的实现思路。

一、核心功能概览

本文实现的 FramelessWidget 继承自 QWidget,去除了系统默认标题栏,同时保留并增强了窗口的核心交互能力,主要功能包括:

  • 无标题栏基础:通过 Qt 窗口标志隐藏系统标题栏
  • 窗口拖拽:鼠标点击内容区可拖拽移动窗口
  • 边缘调整大小:窗口边缘/角落 hover 时切换光标,支持拖拽调整大小
  • 全屏交互:双击窗口切换全屏/正常状态,鼠标靠近顶部也可触发全屏
  • 状态记忆:最小化恢复时,自动还原之前的全屏/正常状态
  • 子部件兼容:通过事件过滤器确保子部件不影响窗口的光标更新与交互

二、代码核心模块解析

2.1 类结构与成员变量

首先看 FramelessWidget 的类定义,核心成员变量用于存储窗口状态、鼠标位置和交互标记,先明确各变量的作用:

cpp 复制代码
class FramelessWidget : public QWidget
{
    Q_OBJECT
public:
    explicit FramelessWidget(QWidget *parent = nullptr);
    ~FramelessWidget();
    void setOldWindowState(Qt::WindowStates state); // 设置历史窗口状态

protected:
    // 重写 Qt 事件处理函数
    void mousePressEvent(QMouseEvent *event) override;
    void mouseMoveEvent(QMouseEvent *event) override;
    void mouseReleaseEvent(QMouseEvent *event) override;
    void mouseDoubleClickEvent(QMouseEvent *event) override;
    bool eventFilter(QObject *obj, QEvent *event) override;
    void changeEvent(QEvent *event) override;
    // 自定义辅助函数
    void handleResize(QMouseEvent *event); // 处理窗口调整大小
    void updateCursorShape(const QPoint &globalPos); // 更新光标形状

private:
    Qt::WindowStates m_OldWindowState; // 最小化前的窗口状态(用于恢复)
    Qt::WindowStates m_WindowState;    // 当前窗口状态
    bool m_readyMove;                  // 是否准备拖拽移动
    QPoint m_currentPos;               // 窗口初始位置(拖拽时用)
    QPoint m_mouseStartPoint;          // 鼠标按下时的全局位置(拖拽时用)
    bool m_resizing;                   // 是否正在调整窗口大小
    int m_resizeEdge;                  // 当前调整的窗口边缘(左/右/上/下/角落)
    QPoint m_resizeStartPos;           // 调整大小开始时的鼠标全局位置
    QRect m_resizeStartGeometry;       // 调整大小开始时的窗口几何信息
};

2.2 构造函数:无标题栏初始化

构造函数是无标题栏窗口的基础,主要完成 3 件核心工作:

  1. 隐藏系统标题栏 :通过 Qt::FramelessWindowHint 标志去除默认标题栏
  2. 启用鼠标跟踪:实时捕获鼠标移动,用于更新光标形状(如边缘 hover 时切换光标)
  3. 安装事件过滤器 :确保子部件(如 QLabelQPushButton)的鼠标事件能被主窗口捕获,避免光标更新失效
cpp 复制代码
const int RESIZE_MARGIN = 10; // 窗口边缘可调整大小的区域宽度(10px)

FramelessWidget::FramelessWidget(QWidget *parent) : QWidget(parent)
{
    // 1. 隐藏系统标题栏
    setWindowFlag(Qt::FramelessWindowHint);
    // 2. 启用鼠标跟踪(不点击也能捕获鼠标移动)
    setMouseTracking(true);
    // 3. 为所有子部件安装事件过滤器
    installEventFilter(this);
}

2.3 鼠标事件处理:拖拽与 Resize

窗口的拖拽移动和边缘调整大小是无标题栏窗口的核心交互,依赖 mousePressEventmouseMoveEventmouseReleaseEvent 三个事件的协同处理。

2.3.1 鼠标按下事件(mousePressEvent)

按下鼠标时,需要判断当前操作是"准备拖拽"还是"准备调整大小":

  • 若鼠标在边缘区域(m_resizeEdge != 0):标记为"准备调整大小",记录初始光标位置和窗口几何信息
  • 若鼠标在内容区:标记为"准备拖拽",记录窗口初始位置和鼠标按下位置
  • 全屏状态下不响应任何按下事件
cpp 复制代码
void FramelessWidget::mousePressEvent(QMouseEvent *event)
{
    if (this->windowState() == Qt::WindowFullScreen)
        return; // 全屏状态不响应

    if (event->button() == Qt::LeftButton)
    {
        if (m_resizeEdge != 0)
        {
            // 边缘按下:开始调整大小
            m_resizing = true;
            m_resizeStartPos = event->globalPos(); // 记录初始鼠标位置
            m_resizeStartGeometry = geometry();    // 记录初始窗口大小
        }
        else
        {
            // 内容区按下:准备拖拽
            m_readyMove = true;
            m_currentPos = frameGeometry().topLeft(); // 窗口初始位置(屏幕坐标)
            m_mouseStartPoint = event->globalPos();   // 鼠标按下位置(屏幕坐标)
        }
    }
}
2.3.2 鼠标移动事件(mouseMoveEvent)

移动鼠标时,根据当前状态(拖拽/Resize/无操作)执行不同逻辑:

  • 若正在调整大小(m_resizing):调用 handleResize 处理窗口大小变化
  • 若正在拖拽(m_readyMove):计算鼠标移动距离,更新窗口位置
  • 若无操作:调用 updateCursorShape 更新光标形状(如边缘 hover 显示 resize 光标)
cpp 复制代码
void FramelessWidget::mouseMoveEvent(QMouseEvent *event)
{
    if (this->windowState() == Qt::WindowFullScreen)
        return; // 全屏状态不响应

    if (m_resizing)
    {
        handleResize(event); // 处理调整大小
    }
    else if (m_readyMove)
    {
        // 计算鼠标移动距离 = 当前鼠标位置 - 按下时的位置
        QPoint moveDistance = event->globalPos() - m_mouseStartPoint;
        // 窗口新位置 = 初始位置 + 移动距离
        move(m_currentPos + moveDistance);
    }
    else
    {
        updateCursorShape(event->globalPos()); // 更新光标形状
    }
}
2.3.3 鼠标释放事件(mouseReleaseEvent)

释放鼠标时,重置交互状态(拖拽/Resize 标记),并添加一个小彩蛋:鼠标靠近屏幕顶部(y ≤ 10px)释放时,触发全屏

cpp 复制代码
void FramelessWidget::mouseReleaseEvent(QMouseEvent *event)
{
    if (event->button() == Qt::LeftButton)
    {
        // 重置交互状态
        m_resizing = false;
        m_readyMove = false;
        m_resizeEdge = 0;
        setCursor(Qt::ArrowCursor); // 恢复默认光标

        // 彩蛋:靠近顶部释放触发全屏
        if (event->globalPos().y() <= 10 && !m_resizing)
        {
            this->setWindowState(Qt::WindowFullScreen);
        }
    }
}

2.4 光标形状更新(updateCursorShape)

根据鼠标在窗口的位置,动态切换光标形状,提升用户体验:

  • 角落(左上/右下):对角 resize 光标(Qt::SizeFDiagCursor
  • 角落(右上/左下):对角 resize 光标(Qt::SizeBDiagCursor
  • 左右边缘:水平 resize 光标(Qt::SizeHorCursor
  • 上下边缘:垂直 resize 光标(Qt::SizeVerCursor
  • 内容区:默认箭头光标(Qt::ArrowCursor

同时处理特殊状态:全屏或最大化时,强制显示默认光标

cpp 复制代码
void FramelessWidget::updateCursorShape(const QPoint &globalPos)
{
    // 全屏/最大化时不改变光标
    if (this->windowState() == Qt::WindowFullScreen || this->isMaximized())
    {
        setCursor(Qt::ArrowCursor);
        return;
    }

    // 将鼠标全局坐标(屏幕)转换为窗口局部坐标
    QPoint localPos = mapFromGlobal(globalPos);
    int x = localPos.x();
    int y = localPos.y();
    int width = this->width();
    int height = this->height();

    // 判断鼠标是否在边缘区域(RESIZE_MARGIN = 10px)
    bool left = x < RESIZE_MARGIN;
    bool right = x > width - RESIZE_MARGIN;
    bool top = y < RESIZE_MARGIN;
    bool bottom = y > height - RESIZE_MARGIN;

    // 根据边缘组合设置光标和 resizeEdge
    if (left && top) { setCursor(Qt::SizeFDiagCursor); m_resizeEdge = Qt::TopEdge | Qt::LeftEdge; }
    else if (left && bottom) { setCursor(Qt::SizeBDiagCursor); m_resizeEdge = Qt::BottomEdge | Qt::LeftEdge; }
    else if (right && top) { setCursor(Qt::SizeBDiagCursor); m_resizeEdge = Qt::TopEdge | Qt::RightEdge; }
    else if (right && bottom) { setCursor(Qt::SizeFDiagCursor); m_resizeEdge = Qt::BottomEdge | Qt::RightEdge; }
    else if (left) { setCursor(Qt::SizeHorCursor); m_resizeEdge = Qt::LeftEdge; }
    else if (right) { setCursor(Qt::SizeHorCursor); m_resizeEdge = Qt::RightEdge; }
    else if (top) { setCursor(Qt::SizeVerCursor); m_resizeEdge = Qt::TopEdge; }
    else if (bottom) { setCursor(Qt::SizeVerCursor); m_resizeEdge = Qt::BottomEdge; }
    else { setCursor(Qt::ArrowCursor); m_resizeEdge = 0; }
}

2.5 窗口大小调整(handleResize)

handleResize 是调整窗口大小的核心逻辑,根据 m_resizeEdge 标记的边缘,计算窗口新的几何形状,并确保窗口不小于设置的最小大小(minimumWidth/minimumHeight)。

例如:

  • 调整左边缘:修改窗口的 left 坐标,若宽度小于最小值,则强制 left = 右边缘 - 最小宽度
  • 调整右边缘:修改窗口的 right 坐标,若宽度小于最小值,则强制 right = 左边缘 + 最小宽度
cpp 复制代码
void FramelessWidget::handleResize(QMouseEvent *event)
{
    QRect newGeometry = m_resizeStartGeometry; // 初始窗口形状
    QPoint delta = event->globalPos() - m_resizeStartPos; // 鼠标移动距离

    // 左边缘调整:修改 left
    if (m_resizeEdge & Qt::LeftEdge)
    {
        newGeometry.setLeft(m_resizeStartGeometry.left() + delta.x());
        // 防止宽度小于最小值
        if (newGeometry.width() < minimumWidth())
        {
            newGeometry.setLeft(m_resizeStartGeometry.right() - minimumWidth());
        }
    }

    // 右边缘调整:修改 right
    if (m_resizeEdge & Qt::RightEdge)
    {
        newGeometry.setRight(m_resizeStartGeometry.right() + delta.x());
        if (newGeometry.width() < minimumWidth())
        {
            newGeometry.setRight(m_resizeStartGeometry.left() + minimumWidth());
        }
    }

    // 上边缘调整:修改 top
    if (m_resizeEdge & Qt::TopEdge)
    {
        newGeometry.setTop(m_resizeStartGeometry.top() + delta.y());
        if (newGeometry.height() < minimumHeight())
        {
            newGeometry.setTop(m_resizeStartGeometry.bottom() - minimumHeight());
        }
    }

    // 下边缘调整:修改 bottom
    if (m_resizeEdge & Qt::BottomEdge)
    {
        newGeometry.setBottom(m_resizeStartGeometry.bottom() + delta.y());
        if (newGeometry.height() < minimumHeight())
        {
            newGeometry.setBottom(m_resizeStartGeometry.top() + minimumHeight());
        }
    }

    // 应用新的窗口形状
    setGeometry(newGeometry);
}

2.6 全屏切换与状态记忆

2.6.1 双击切换全屏(mouseDoubleClickEvent)

双击窗口左键时,根据当前状态切换全屏/正常状态:

  • 若当前是全屏:切换为正常状态(Qt::WindowNoState
  • 若当前是正常状态:切换为全屏(Qt::WindowFullScreen
cpp 复制代码
void FramelessWidget::mouseDoubleClickEvent(QMouseEvent *event)
{
    if (event->button() == Qt::LeftButton)
    {
        if (this->windowState() == Qt::WindowFullScreen)
            this->setWindowState(Qt::WindowNoState); // 全屏 → 正常
        else
            this->setWindowState(Qt::WindowFullScreen); // 正常 → 全屏
    }
}
2.6.2 状态记忆(changeEvent)

当窗口状态变化时(如最小化、恢复),通过 changeEvent 记忆历史状态,避免最小化后恢复时丢失全屏状态:

  • 若之前是最小化(m_WindowState == Qt::WindowMinimized),且恢复时不是全屏,则检查 m_OldWindowState
  • m_OldWindowState 是全屏,则恢复为全屏
cpp 复制代码
void FramelessWidget::changeEvent(QEvent *event)
{
    if (event->type() == QEvent::WindowStateChange)
    {
        // 最小化恢复时,还原之前的全屏状态
        if (m_WindowState == Qt::WindowMinimized && this->windowState() != Qt::WindowFullScreen)
        {
            if (m_OldWindowState == Qt::WindowFullScreen)
            {
                this->setWindowState(Qt::WindowFullScreen);
            }
        }
        // 更新当前窗口状态
        m_WindowState = this->windowState();
    }
    QWidget::changeEvent(event);
}

通过 setOldWindowState 函数,外部可手动设置历史状态,例如在自定义标题栏的"最小化"按钮中调用:

cpp 复制代码
void MyTitleBar::onMinimizeClicked()
{
    // 保存当前状态,用于恢复时判断是否全屏
    m_framelessWidget->setOldWindowState(m_framelessWidget->windowState());
    m_framelessWidget->showMinimized();
}

2.7 事件过滤器(eventFilter)

Qt 中,子部件(如 QPushButton)会优先捕获鼠标事件,导致主窗口无法收到鼠标移动事件,进而光标形状无法更新。通过事件过滤器,可将子部件的 MouseMove 事件传递给主窗口,确保光标更新正常。

cpp 复制代码
bool FramelessWidget::eventFilter(QObject *obj, QEvent *event)
{
    // 子部件的鼠标移动事件,传递给主窗口处理(更新光标)
    if (event->type() == QEvent::MouseMove && !m_resizing && !m_readyMove)
    {
        QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
        updateCursorShape(mouseEvent->globalPos());
    }
    // 其他事件按默认逻辑处理
    return QWidget::eventFilter(obj, event);
}

三、使用示例

FramelessWidget 是一个基础类,可直接继承使用,或作为主窗口的基类。以下是一个简单示例:

cpp 复制代码
// 1. 自定义窗口类,继承 FramelessWidget
#include "framelesswidget.h"
#include <QLabel>
#include <QVBoxLayout>

class MyMainWindow : public FramelessWidget
{
    Q_OBJECT
public:
    MyMainWindow(QWidget *parent = nullptr) : FramelessWidget(parent)
    {
        // 设置窗口最小大小(避免 resize 过小)
        setMinimumSize(800, 600);
        // 设置窗口背景色(区分内容区)
        setStyleSheet("background-color: #f5f5f5;");

        // 添加内容(示例:一个标签和按钮)
        QVBoxLayout *layout = new QVBoxLayout(this);
        layout->setContentsMargins(20, 20, 20, 20); // 内边距

        QLabel *titleLabel = new QLabel("Qt 无标题栏窗口示例", this);
        titleLabel->setStyleSheet("font-size: 28px; color: #333; font-weight: bold;");
        titleLabel->setAlignment(Qt::AlignCenter);

        QPushButton *testBtn = new QPushButton("测试按钮", this);
        testBtn->setStyleSheet("padding: 10px 20px; font-size: 16px;");

        layout->addWidget(titleLabel);
        layout->addWidget(testBtn);
        layout->addStretch(); // 拉伸填充
    }
};

// 2. main 函数中使用
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MyMainWindow w;
    w.show(); // 显示窗口
    return a.exec();
}

四、源码

cpp 复制代码
#include "framelesswidget.h"
#include <QMouseEvent>
#include <QCoreApplication>

const int RESIZE_MARGIN = 10;

FramelessWidget::FramelessWidget(QWidget *parent) : QWidget(parent)
{
    setWindowFlag(Qt::FramelessWindowHint);
    // 启用鼠标跟踪
    setMouseTracking(true);
    // 为所有子部件启用鼠标跟踪
    installEventFilter(this);
}

FramelessWidget::~FramelessWidget()
{
}

void FramelessWidget::setOldWindowState(Qt::WindowStates state)
{
    m_OldWindowState = state;
}

void FramelessWidget::mousePressEvent(QMouseEvent *event)
{
    if (this->windowState() == Qt::WindowFullScreen)
    {
        // 全屏状态下,不响应鼠标事件
        return;
    }

    if (event->button() == Qt::LeftButton)
    {
        if (m_resizeEdge != 0)
        {
            // 如果在边缘区域按下,开始调整大小
            m_resizing = true;
            m_resizeStartPos = event->globalPos();
            m_resizeStartGeometry = geometry();
        }
        else
        {
            // 鼠标在窗口内容区域按下了左键,准备开始移动
            m_readyMove = true;
            // 记录当前窗口和鼠标的位置
            m_currentPos = frameGeometry().topLeft();
            m_mouseStartPoint = event->globalPos();
        }
    }
}

void FramelessWidget::mouseMoveEvent(QMouseEvent *event)
{
    if (this->windowState() == Qt::WindowFullScreen)
    {
        // 全屏状态下,不响应鼠标事件
        return;
    }

    if (m_resizing)
    {
        // 正在调整窗口大小
        handleResize(event);
    }
    else if (m_readyMove)
    {
        // 正在移动窗口
        QPoint moveDistance = event->globalPos() - m_mouseStartPoint;
        move(m_currentPos + moveDistance);
    }
    else
    {
        // 更新鼠标光标形状
        updateCursorShape(event->globalPos());
    }
}

void FramelessWidget::mouseReleaseEvent(QMouseEvent *event)
{
    if (event->button() == Qt::LeftButton)
    {
        m_resizing = false;
        m_readyMove = false;
        m_resizeEdge = 0;

        // 恢复默认光标
        setCursor(Qt::ArrowCursor);

        // 靠近顶部全屏
        if (event->globalPos().y() <= 10 && !m_resizing)
        {
            this->setWindowState(Qt::WindowFullScreen);
        }
    }
}

void FramelessWidget::updateCursorShape(const QPoint &globalPos)
{
    if (this->windowState() == Qt::WindowFullScreen || this->isMaximized())
    {
        setCursor(Qt::ArrowCursor);
        return;
    }

    // 将全局坐标转换为窗口内的局部坐标
    QPoint localPos = mapFromGlobal(globalPos);
    int x = localPos.x();
    int y = localPos.y();
    int width = this->width();
    int height = this->height();

    // 检测鼠标在哪个边缘区域
    bool left = x < RESIZE_MARGIN;
    bool right = x > width - RESIZE_MARGIN;
    bool top = y < RESIZE_MARGIN;
    bool bottom = y > height - RESIZE_MARGIN;

    if (left && top)
    {
        setCursor(Qt::SizeFDiagCursor);
        m_resizeEdge = Qt::TopEdge | Qt::LeftEdge;
    }
    else if (left && bottom)
    {
        setCursor(Qt::SizeBDiagCursor);
        m_resizeEdge = Qt::BottomEdge | Qt::LeftEdge;
    }
    else if (right && top)
    {
        setCursor(Qt::SizeBDiagCursor);
        m_resizeEdge = Qt::TopEdge | Qt::RightEdge;
    }
    else if (right && bottom)
    {
        setCursor(Qt::SizeFDiagCursor);
        m_resizeEdge = Qt::BottomEdge | Qt::RightEdge;
    }
    else if (left)
    {
        setCursor(Qt::SizeHorCursor);
        m_resizeEdge = Qt::LeftEdge;
    }
    else if (right)
    {
        setCursor(Qt::SizeHorCursor);
        m_resizeEdge = Qt::RightEdge;
    }
    else if (top)
    {
        setCursor(Qt::SizeVerCursor);
        m_resizeEdge = Qt::TopEdge;
    }
    else if (bottom)
    {
        setCursor(Qt::SizeVerCursor);
        m_resizeEdge = Qt::BottomEdge;
    }
    else
    {
        setCursor(Qt::ArrowCursor);
        m_resizeEdge = 0;
    }
}

void FramelessWidget::handleResize(QMouseEvent *event)
{
    QRect newGeometry = m_resizeStartGeometry;
    QPoint delta = event->globalPos() - m_resizeStartPos;

    if (m_resizeEdge & Qt::LeftEdge)
    {
        newGeometry.setLeft(m_resizeStartGeometry.left() + delta.x());
        if (newGeometry.width() < minimumWidth())
        {
            newGeometry.setLeft(m_resizeStartGeometry.right() - minimumWidth());
        }
    }

    if (m_resizeEdge & Qt::RightEdge)
    {
        newGeometry.setRight(m_resizeStartGeometry.right() + delta.x());
        if (newGeometry.width() < minimumWidth())
        {
            newGeometry.setRight(m_resizeStartGeometry.left() + minimumWidth());
        }
    }

    if (m_resizeEdge & Qt::TopEdge)
    {
        newGeometry.setTop(m_resizeStartGeometry.top() + delta.y());
        if (newGeometry.height() < minimumHeight())
        {
            newGeometry.setTop(m_resizeStartGeometry.bottom() - minimumHeight());
        }
    }

    if (m_resizeEdge & Qt::BottomEdge)
    {
        newGeometry.setBottom(m_resizeStartGeometry.bottom() + delta.y());
        if (newGeometry.height() < minimumHeight())
        {
            newGeometry.setBottom(m_resizeStartGeometry.top() + minimumHeight());
        }
    }

    setGeometry(newGeometry);
}

bool FramelessWidget::eventFilter(QObject *obj, QEvent *event)
{
    // 将鼠标移动事件传递给主窗口,用于更新光标形状
    if (event->type() == QEvent::MouseMove && !m_resizing && !m_readyMove)
    {
        QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
        updateCursorShape(mouseEvent->globalPos());
    }
    return QWidget::eventFilter(obj, event);
}

void FramelessWidget::mouseDoubleClickEvent(QMouseEvent *event)
{
    if (event->button() == Qt::LeftButton)
    {
        if (this->windowState() == Qt::WindowFullScreen)
        {
            this->setWindowState(Qt::WindowNoState);
        }
        else
        {
            this->setWindowState(Qt::WindowFullScreen);
        }
    }
}

void FramelessWidget::changeEvent(QEvent *event)
{
    if (event->type() == QEvent::WindowStateChange)
    {
        if (m_WindowState == Qt::WindowMinimized && this->windowState() != Qt::WindowFullScreen)
        {
            if (m_OldWindowState == Qt::WindowFullScreen)
            {
                this->setWindowState(Qt::WindowFullScreen);
            }
        }
        m_WindowState = this->windowState();
    }
    QWidget::changeEvent(event);
}
相关推荐
IccBoY6 小时前
Java采用easyexcel组件进行excel表格单元格的自动合并
java·开发语言·excel
tt5555555555556 小时前
C++ 经典数组算法题解析与实现教程
开发语言·c++·算法
会跑的葫芦怪6 小时前
Go语言操作Redis
开发语言·redis·golang
泽虞7 小时前
《Qt应用开发》笔记
linux·开发语言·c++·笔记·qt
专职7 小时前
pytest详细教程
开发语言·python·pytest
专职7 小时前
pytest+requests+allure生成接口自动化测试报告
开发语言·python·pytest
风起云涌~7 小时前
【Java】浅谈ServiceLoader
java·开发语言
那我掉的头发算什么7 小时前
【数据结构】优先级队列(堆)
java·开发语言·数据结构·链表·idea
.ZGR.8 小时前
C语言:数组的增删查改2.0
c语言·开发语言