【Qt6】QWindow类可以做什么

这篇具有很好参考价值的文章主要介绍了【Qt6】QWindow类可以做什么。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

原来的水文标题是“用 VS Code 搞 Qt6”,想想还是直接改为“Qt6”,反正这个用不用 VS Code 也能搞。虽然我知道大伙伴们都很讨厌 CMake,但毕竟这厮几乎成了 C++ 的玩家规范了。Qt 也算识大体,支持用 CMake 来构建程序。所以,只要你用的是能写 C++ 的工具,理论上都能搞 Qt。

创建应用程序界面的时候,我们一般会选用 QWidget 以及其子类的。不过,在 Gui 模块中,有一个 QWindow 类,干吗用的呢?写个程序试试看。

#include <QGuiApplication>
#include <QWindow>

int main(int argc, char** argv)
{
    // 一定要先创建应用程序对象
    QGuiApplication app(argc, argv);
    // 创建窗口实例
    QWindow win;
    // create方法其实可以不调用
    win.create();
    // 调整窗口的大小
    win.resize(300, 250);
    // 设置标题栏文本
    win.setTitle("番薯联盟");
    // 显示窗口
    win.show();
    // exec进入事件(消息)循环
    return QGuiApplication::exec();
}

这里说明一下,QWindow 类有个 create 方法,它的作用是创建平台相关的资源的,对应的是 destroy 方法,用来销毁这些平台相关的资源。这些平台相关的资源是为了实现跨平台的类型,如 QPlatformWindow、QPlatformSurfaceEvent 之类的。Windows 平台有单独的实现,Linux 平台也单独地实现。像 qwindowsguieventdispatcher、qunixeventdispatcher 这些也是。总之,QWindow 类可能会用到它们,于是,这些平台相关的资源,其生命周期始于 create 方法,终于 destroy 方法。

不过,create 方法这里其实可以不调用的,因为 show 方法会调用;destroy 方法也不可以不调用,它在 QWindow 类的析构函数中被调用。

咱们为上述代码写一个 CMakeLists.txt。

cmake_minimum_required(VERSION 3.0.0)
project(TestApp VERSION 0.1.0)

find_package(Qt6 REQUIRED COMPONENTS Core Gui)

add_executable(TestApp main.cpp)
target_link_libraries(TestApp PRIVATE Qt6::Core Qt6::Gui)

这里我们不到“铁三角”库,只用 core 和 gui 就够了,不需要 widgets。

好了,尝试运行,看看会出现什么。

【Qt6】QWindow类可以做什么

这标题栏上的字体好像有问题。不管它,继续。

哦,直接实例化 QWindow 类会呈现一个空白窗口,而且这个窗口很诡异,你拖动一下改变它的大小后,就会变成这样。

【Qt6】QWindow类可以做什么

 这是因为这个窗口是真的很空,空到连基本的绘制都没有,只是在启动的时候填充了个颜色。这个颜色是跟随系统主题的,刚才你看到的是深色主题下的背景色。现在我把系统主题调成浅色主题,它就会变成这样。

【Qt6】QWindow类可以做什么

当你调整其大小后,发生重新绘制的部分变成了黑色(就是啥也没有)。

QWindow 类虽然定义了 paintEvent 方法,但是,它实现了个寂寞。

void QWindow::paintEvent(QPaintEvent *ev)
{
    ev->ignore();
}

从源代码中你会看到,默认的实现是直接把 paint 事件忽略了。

所以,我们只能从 QWindow 类派生,并重写 paintEvent 方法,绘制我们所需要的内容。

cmake_minimum_required(VERSION 3.0.0)
project(TestApp VERSION 1.2.3)

find_package(Qt6 REQUIRED COMPONENTS Core Gui)
set(CMAKE_AUTOMOC ON)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

add_executable(TestApp MyWindow.h MyWindow.cpp main.cpp)

target_link_libraries(TestApp PRIVATE Qt6::Core Qt6::Gui)

 文章来源地址https://www.toymoban.com/news/detail-422814.html

 1 #include <QWindow>
 2 #include <QPaintEvent>
 3 #include <QBackingStore>
 4 
 5 #ifndef __MYWINDOW_H__
 6 #define __MYWINDOW_H__
 7 class MyWindow : public QWindow
 8 {
 9     Q_OBJECT
10 public:
11     // 构造函数
12     explicit MyWindow(QWindow* parent = nullptr);
13 protected:
14     // 重写事件
15     void paintEvent(QPaintEvent *ev) override;
16 private:
17     // 绘制窗口内容需要这个类
18     QBackingStore* m_backstore;
19 };
20 #endif

要在窗口上涂鸦,需要用到 QBackingStore 类。这是由于 QPainter 类需要一个 QPaintDevice 指针才能完成绘图。QBackingStore类可以通过 paintDevice 方法返回一个 QPaintDevice 类的指针。

m_backstore 成员也可以用 QScopedPointer 封装,防止内存泄漏。

private:
    // 绘制窗口内容需要这个类
    QScopedPointer<QBackingStore> m_backstore;

当超出成员作用域时会自动删除指针。

下面是实现代码。

#include "MyWindow.h"
#include <QPaintDevice>
#include <QPainter>
#include <QColor>
#include <QRect>
#include <QtDebug>

MyWindow::MyWindow(QWindow* parent)
    : QWindow(parent), 
      m_backstore(new QBackingStore(this))
{
    // 设置当前窗口的位置和大小
    setGeometry(799, 304, 425, 385);
    // 设置绘画设备画布大小
    m_backstore -> resize(QSize(400, 300));
    // 设置窗口标题
    setTitle("红红火火");
}

void MyWindow::paintEvent(QPaintEvent* ev)
{
    // 要进行绘图的区域
    QRect rect = ev->rect();
    // 开始
    m_backstore->beginPaint(rect);
    QPaintDevice* dev = m_backstore -> paintDevice();
    // 创建painter实例
    QPainter painter;
    painter.begin(dev);
    // 填充矩形
    painter.fillRect(rect, QColor("red"));
    painter.end();
    // 结束
    m_backstore->endPaint();
    // 把绘图输出到窗口上
    m_backstore->flush(rect);
}

QBackingStore 类的构造函数需要一个 QWindow 类或子类的指针,一般是当前窗口类。这里注意的是,QBackingStore 对象不能使用默认大小(程序会闪退),一定要调用 resize 方法设置画布的大小(或者说你能看到的视窗大小)。

当窗口需要绘制时会引发 paint 事件,重写 paintEvent 方法自行绘制窗口内容。在上面代码中,只是简单的矩形填充(填充为红色)。

    m_backstore->beginPaint(rect);
    QPaintDevice* dev = m_backstore -> paintDevice();
    // 创建painter实例
    QPainter painter;
    painter.begin(dev);
    // 填充矩形
    painter.fillRect(rect, QColor("red"));
    painter.end();
    // 结束
    m_backstore->endPaint();
    // 把绘图输出到窗口上
    m_backstore->flush(rect);

QBackingStore.paintDevice 方法所返回的 QPaintDevice 指针只在 beginPaint 和 endPaint 方法之间有效。QPaintDevice 是一个虚拟设备,用于构建二维坐标空间,然后才能在上面绘图。绘图用到 QPainter 类。这个类在实例化后,调用 begin 方法开始绘图,前面获取的 QPaintDevice 指针就在这里传递。绘制完后调用 end 方法结束。如果实例化 QPainter 类时向构造函数传递了 QPaintDevice 指针,那就不需要调用 begin 方法了。

    QPainter painter(dev);
    //painter.begin(dev);
    // 填充矩形
    painter.fillRect(rect, QColor("red"));
    painter.end();

最后,main 函数中实例化 MyWindow,并显示它。

int main(int argc, char** argv)
{
    // 一定要先创建应用程序对象
    QGuiApplication app(argc, argv);
    // 创建窗口实例
    MyWindow win;
    // 显示窗口
    win.show();
    // exec进入事件(消息)循环
    return QGuiApplication::exec();
}

运行程序,看到红红的一块,就说明通正确运行了。

【Qt6】QWindow类可以做什么

当然,这个窗口还是有问题的。由于 QBackingStore 对象的画布大小是硬编码的,当调整了窗口大小后,红色矩形只能看到一部分,没看到的那部分仍然是黑乎乎的。

为了完善一下,我们还要重写 resizeEvent 函数,在窗口的大小被调整后,手动修改 QBackingStore 的画布大小。

class MyWindow : public QWindow
{
    Q_OBJECT
    ……
protected:
    ……
    // 调整窗口大小后发生
    void resizeEvent(QResizeEvent* ev) override;
    ……
};
void MyWindow::resizeEvent(QResizeEvent *ev)
{
    this->m_backstore->resize(ev->size());
}

这样处理之后,窗口的背景色就能正常绘制了,哪怕你调整了窗口大小。

【Qt6】QWindow类可以做什么

 

直接从 QWindow 类继承还是不太方便的,内部还要使用 QBackingStore 类。于是,我们可以考虑用 QWindow 的派生类。比如 QRasterWindow。这个类是用于创建基于像素呈现的窗口——相对应的是 QOpenGLWindow。两者用法差不多,只是绘制方式不同罢了。

QRasterWindow和QOpenGLWindow类都是 QPaintDevice 和 QWindow 的子类,所以从 QRasterWindow 派生的自定义窗口不需要定义 QBackingStore成员了,窗口自身的实例就可以传递给 QPainter 对象。

接下来咱们演示一下。先编好 CMakeLists.txt 文件。

cmake_minimum_required(VERSION 3.8)
project(HelloApp VERSION 1.0.0 LANGUAGES CXX)
# Qt内裤包
find_package(Qt6 REQUIRED COMPONENTS
                Core
                Gui)
# 开启MOC等选项
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED YES)
set(CMAKE_AUTOMOC YES)

# 代码目录
file(GLOB SRCS src/*.cpp includes/*.h)
# 添加可执行代码
add_executable(HelloApp ${SRCS})
# 链接Qt内裤
target_link_libraries(HelloApp PRIVATE
                        Qt6::Core
                        Qt6::Gui)

这里老周学会了偷懒,用 file 指令找出 includes 目录下所有扩展名为 .h 的文件, 以及 src 目录下所有扩展名为 .cpp 的文件。然后把结果存到 SRCS 变量中,在 add_executable 命令执行时直接把 SRCS 传给它。这样做的好处是不用每新建一个文件都要手动添加一次了。当 IDE 提示找不到头文件时,执行一次 CMake 配置就会触发 file 命令。项目的目录结构大致长这样:

【Qt6】QWindow类可以做什么

同理,这里咱们只用到 Core 和 Gui 两个模块,不需要 Widgets。

CustWindow 类派生自 QRasterWindow 类,重写 paintEvent 方法,自行绘制窗口内容。

#include <QRasterWindow>
#include <QPaintEvent>

#ifndef __CUSTWINDOW_H__
#define __CUSTWINDOW_H__
class CustWindow : public QRasterWindow
{
    Q_OBJECT

protected:
    void paintEvent(QPaintEvent* event) override;
};
#endif

下面是实现代码。

#include "../includes/CustWindow.h"
#include <QPainter>

void CustWindow::paintEvent(QPaintEvent *event)
{
    QPainter painter;
    painter.begin(this);
    // 要绘制的区域
    QRect rect = event->rect();
    // 先刷刷墙壁
    painter.fillRect(rect, QColor("blue"));
    // 刷累了画个大饼充饥
    // 换支笔
    QPen pen(QColor("yellow"), 3.0f);
    painter.setPen(pen);
    rect.adjust(50, 50, -50, -50);
    painter.drawEllipse(rect);
    // 收工
    painter.end();
}

在实例化 QPainter 时,可以把当前窗口指针 this 传递给 QPainter 的构造函数;或者先调用无参构造函数,然后调用 begin 方法传递 this。前面说过,QRasterWindow 类的父类中有 QPaintDevice,所以咱们的窗口类自然就能直接传给 QPainter 对象了。

这里头的继承关系是这样的:

QWindow、QPaintDevice => QPaintDeviceWindow => QRasterWindow => CustWindow

C++ 是可以多继承的,所以 QPaintDevice 能有两个基类。

app.cpp 文件中写 main 函数。

#include "../includes/CustWindow.h"
#include <QGuiApplication>

int main(int argc, char* argv[])
{
    QGuiApplication app(argc, argv);

    // 实例化窗口
    CustWindow window;
    // 设置标题和大小
    window.setTitle("Bug App");
    window.resize(450, 450);
    // 显示窗口
    window.show();

    return app.exec();
}

运行一下,看看咱们画的大饼,又大又黄。

【Qt6】QWindow类可以做什么

 

看到这里,相信大伙伴们都了解 QWindow 怎么玩了。于是,咱们回归标题,这个类到底干吗呢?与 QWidget 类比如何?

1、QWindow 比 QWidget 更复杂,更难用,更麻烦,是一盏很浪费油的灯;

2、可是,它也不是没用的。QWidget 测重组件化,封装得好,开柜即用,方便组装。而 QWindow 更抽象,更高级,更灵活,用来装逼直接爆表。比如你有一个窗口只用来画一个图表,告诉用户,他最近抑郁症发作的频率和趋势,以及预测什么时候无可救药。这种情形就很适合使用 QWindow 来创建窗口。

总的来说,QWindow 类能做的事情更多,但需要投入的开发成本更高,代码量更吓人。我们知道,其实窗口上的控件(比如按钮、标签、复选框等)本质上也是窗口对象——只是嵌套在顶层窗口中,成了子窗口罢了。

QWindow 对象也可以嵌套使用的,这个老周会在下一篇水文中介绍。故,QWindow 类不仅能灵活的创建窗口,也能自制许多控件。

 

到了这里,关于【Qt6】QWindow类可以做什么的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Java原来可以这么玩!CV实现多张图片生成视频

    比如我像将几张图片变成一个视频的形式发不到短视频平台,虽然短视频平台也有上传图片变成视频的功能,但是我想要具体控制每张图片显示多久后切换到下一个图片,短视频平台目前无法实现,于是乎,我用java代码实现了这个功能。 生成视频展示 多张图片生成视频 Ja

    2024年01月17日
    浏览(49)
  • 不直播拍视频,一样可以变现,原来是做了这个!

    我是电商珠珠 随着直播带货的流行,部分大学也开始紧随其后,相继增设网络营销与直播电商这项课程。 以上这些技能,部分人并不知道怎么搞,一是不想麻烦,没那么多时间精力,二是做不起来,自身没有那些才艺,吸引不到粉丝。 既然直播带货不行,那么就另谋他法。

    2024年02月08日
    浏览(42)
  • 百行Python代码开发出游戏,原来Python可以这么强大!

    安装pygame 下载对应python版本的pygame 运行以下命令 创建Pygame窗口及响应用户输入 新建一个文件夹alien_invasion,并在文件夹中新建alien_invasion.py文件,输入如下代码。 运行上述代码,我们可以得到一个灰色界面的窗口: 创建设置类 为了在写游戏的过程中能便捷地创建一些新功

    2024年04月22日
    浏览(38)
  • QT6 for android 安装教程记录(版本Qt6.5.2)

    本文记录首次安装QT for andriod的详细记录。 网上的信息和资料非常多,收集和整理以及遇到的问题也各异,对新手首次接触相关开发和部署环境并不是清晰,因此,特将相关详细配置记录。 首先,开发QT for andriod 不建议使用QT5.15的版本,因为该版本不能区分相关的CPU架构,而

    2024年02月03日
    浏览(52)
  • C语言初学者:原来分支和循环语句可以这样简单!

    目录 1.分支语句 1.if 语句 2.else语句 3.嵌套if  4.悬空else的问题 5.Switch语句 2.循环语句  1.while循环 2.for循环 3do-while循环 3.break和continue语句 1.break语句 2.continue语句 4.goto语句  5.小结 6.为你们点赞呢~ 7.完结散花                            不是每个人都能做自己想做的事,成

    2024年04月12日
    浏览(46)
  • 活用 F12 开发者工具,测试效率原来可以提高这么多

    F12开发者工具是浏览器自带的一个开发调试工具,因为可以用F12快捷键直接启动,所以简称为F12工具。 F12工具因为有如下的特点,所以被开发和测试人员广泛使用: 1.简单轻量免安装,是浏览器内置的开发者工具,可以提供捕获浏览器的数据报文的功能; 2.作为浏览器的一部

    2024年02月04日
    浏览(54)
  • Java原来可以这么玩!CV视频合成处理,视频前后拼接,画面合并

    本章内容教会你如何用java代码实现 两个视频的画面合并 或者前后拼接。原理是使用了javacv开源jar包,代码经过反复修改,已经实现我能想到的最优最快的实现,如果你有更好更快的实现,欢迎评论区留言!!! 先展示一下效果吧!!! 两个视频前后拼接 两个视频画面合并

    2024年01月21日
    浏览(46)
  • 【QT教程】QT6物联网应用

    QT6物联网应用 使用AI技术辅助生成 QT界面美化视频课程 QT性能优化视频课程 QT原理与源码分析视频课程 QT QML C++扩展开发视频课程 免费QT视频课程 您可以看免费1000+个QT技术视频 免费QT视频课程 QT统计图和QT数据可视化视频免费看 免费QT视频课程 QT性能优化视频免费看 免费QT视

    2024年04月25日
    浏览(39)
  • Qt6中使用Qt Charts

     官方文档:Qt Charts 6.5.2           如果你是使用  CMake 构建的,则应在  CMakeLists.txt  中添加如下两行代码:         其中  mytarget 为你的项目名称。一共2处改动,如下截图:         改完之后,你在 .cpp 文件导入库名,就可以开始画图了。         关于怎么画出一个可

    2024年02月09日
    浏览(41)
  • 【Qt6】QStringList

    2023年10月31日,周二上午 QStringList 是 Qt 中的一个类,用于存储一组字符串。它提供了一些方便的方法来操作和管理字符串列表。 QStringList 可以用于存储任意数量的字符串,并提供了一些常用的操作,例如添加、删除、查找、排序等。它是基于 QStringList 类的 QVectorQString 的封装

    2024年02月06日
    浏览(36)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包