【Qt6】嵌套 QWindow

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

在上个世纪的文章中,老周简单介绍了 QWindow 类的基本使用——包括从 QWindow 类派生和从 QRasterWindow 类派生。

其实,QWindow 类并不是只能充当主窗口用,它也可以嵌套到父级窗口中,变成子级对象。咱们一般称之为【控件】。F 话不多讲,下面咱们用实际案例来说明。

这个例子中老周定义了两个类:

MyControl:子窗口对象,充当控件角色。这里实现一个类似开关的控件。【关闭】状态下,控件的背景呈现为灰色,金色方块位于最左侧;当控件处于【开启】状态下,控件背景为红色,金色方块位于最右侧。
MyWindow:作为窗口使用,里面包含 MyControl 对象。
先看 MyControl 类。
class MyControl : public QRasterWindow
{
    Q_OBJECT

public:
    MyControl(QWindow *parent = nullptr);

private:
    // “开启”状态时的背景色
    QColor _on_bgcolor;
    // “关闭”状态时的背景色
    QColor _off_bgcolor;
    // 当前状态
    bool _state;

signals:
    // 信号
    void stateChanged(bool isOn);

public:
    // 获取状态
    inline bool state() const { return _state; }
    // 修改状态
    inline void setState(bool s)
    {
        _state = s;
        // 发出信号
        emit stateChanged(_state);
    }

protected:
    // 重写方法
    void paintEvent(QPaintEvent *event) override;
    void mousePressEvent(QMouseEvent* evebt) override;
};

在私有成员中,两个 QColor 类型的变量分别表示控件处于【开】或【关】状态时的背景色。_state 是一个布尔值,true就是【开】,false就是【关】,用来存储控件的当前状态。

公共方法 state 获取当前状态,setState 方法用来修改当前状态,同时会发出 stateChanged 信号。信号成员咱们先放一下,后文再叙。

两个虚函数的重写。paintEvent 负责画出控件的模样;mousePressEvent 当鼠标左键按下时改变控件的状态。实现点击一下开启,再点击一下关闭的功能。

接下来是实现各个成员。先是构造函数。

MyControl::MyControl(QWindow* parent)
    :QRasterWindow::QRasterWindow(parent),
     _state(false),
     _on_bgcolor(QColor("red")),
     _off_bgcolor(QColor("gray"))
{

}

构造函数主要用来初始化几个私有成员。下面代码实现鼠标左键按下后更改状态。

void MyControl::mousePressEvent(QMouseEvent *event)
{
    if(! (event->buttons() & Qt::MouseButton::LeftButton))
        return;  // 如果按的不是左键就 PASS
    
    this->setState(!this->state());
    update();
}

每次点击后控件的状态都会取反(开变关,关变开),为了反映改变必须重新绘制控件,所以要调用 update 方法。

paintEvent 中实现绘制的过程。

void MyControl::paintEvent(QPaintEvent* event)
{
    // 如果当前为不可见状态,就不绘图了
    if(!isExposed())
        return;
    // 要绘制的区域
    QRect rect = event -> rect();

    QPainter painter;
    painter.begin(this);
    // 根据状态填充背景
    QBrush bgbrush;
    bgbrush.setStyle(Qt::SolidPattern);
    if(_state)
    {
        bgbrush.setColor(_on_bgcolor);
    }
    else
    {
        bgbrush.setColor(_off_bgcolor);
    }
    painter.fillRect(rect, bgbrush);

    QRect rectSq;
    // 如果是“开”的状态,绿色矩形在右侧
    if(_state)
    {
        rectSq.setX(rect.width() / 3 * 2);
        rectSq.setWidth(rect.width() / 3);
    }
    // 如果为“关”的状态,绿色矩形在左侧
    else{
        rectSq.setWidth(rect.width() / 3);
    }
    rectSq.setHeight(rect.height());
    painter.fillRect(rectSq, QColor("gold"));
    painter.end();
}

绘制分两步走。第一步是填充背景矩形,如果【开】就填充红色,如果【关】就填充灰色。此处用到了 QBrush 对象。根据不同颜色调用 setColor 方法来设置。这里要注意 QBrush 对象要调用 setStyle 方法设置画刷样式为 SolidPattern。这是因为 QBrush 类默认的 style 是 NoBrush,因此要手动设置一下,不然看不到绘制。

第二步是绘制小方块。当控件状态为【开】时方块在右边,状态为【关】时方块在左边。小方块的宽度是控件宽度的 1/3,高度与控件相同。要显式调用 setHeight 方法设置矩形高度(因为它默认为0)。记得小方块的左上角的 X 坐标也要调整的。

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

下面是窗口 MyWindow 的成员。

class MyWindow : public QRasterWindow
{
    Q_OBJECT

public:
    MyWindow(QWindow *parent = nullptr);

private:
    MyControl *_control;
    void initUI();

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

重写的 paintEvent 方法负责画窗口的背景。私有成员 initUI 用于初始化子窗口(MyControl对象)。initUI 方法在构造函数中调用。

MyWindow::MyWindow(QWindow *parent)
    :QRasterWindow::QRasterWindow(parent)
{
    initUI();
}

void MyWindow::initUI()
{
    // 初始化窗口
    setTitle("示例程序");
    resize(550, 450);
    setMinimumSize(QSize(340, 200));
    _control = new MyControl(this);
    // 初始化子窗口
    _control->setPosition(35, 40);
    _control->resize(120, 35);
    _control->setVisible(true);
}

setVisible 方法使用控件变为可见,只有可见的对象才能被看到。

paintEvent 方法只负责画窗口背景。

void MyWindow::paintEvent(QPaintEvent *event)
{
    // 只填充窗口
    QPainter painter(this);
    painter.fillRect(event->rect(), QColor("blue"));
    painter.end();
}

 

最后写 main 函数。

int main(int argc, char** argv)
{
    QGuiApplication app(argc, argv);
    MyWindow wind;
    wind.show();
    return QGuiApplication::exec();
}

 

运行后,点一下子窗口,它就会改变颜色。

【Qt6】嵌套 QWindow

 

 关于控件周围有白边(或黑边)的问题:

这个问题比较不确定,不同平台好像表现不一样。Windows 下在控件周围会多出白色区域(也可能是黑色);在 Debian 下没有出现白边。所以,为了尽可能地避免跨平台差异导致的问题,可以用 mask 让控件区域之外的地方变为透明,这样白边黑边就会消失。

调用 setMask 方法要在重写的 resizeEvent 方法中进行,这是为了响应控件大小改变后,及时调整要透明的区域。

void MyControl::resizeEvent(QResizeEvent *event)
{
    setMask(QRect(QPoint(), event->size()));
}

 

刚才,咱们 MyControl 类定义了 stateChanged 信号,并在修改控件状态后发出。接下来我们用一个 lambda 表达式来充当 slot,当控件状态改变后输出调试信息(使用 qDebug 宏)。

connect(_control, &MyControl::stateChanged, this, [](bool st){
    qDebug() << "当前状态:" << st;
});

再次运行程序,每点击一下控件,控制台就会输出一条调试信息。

【Qt6】嵌套 QWindow

 

 setMask 还有一个经典用途——制作透明窗口。下面咱们顺便讨论一下如何做不规则形状的窗口。

a、调用 setFlags 方法设置 WindowType::FramelessWindowHint 标志,去掉窗口的边框;

b、调用 setMask 方法时需要传递一个 QRegion 对象,它表示一个形状区域。这个区域可以是矩形,也可以是圆形,当然也可以是多边形。设置 mask 后,指定区域外的内容变成透明,并且不会响应用户的输入事件(鼠标、键盘等)。QRegion 对象可以进行 and、or 等运算,多个区域可以进行交集或并集处理,形成各种不规则图形。

 

咱位做个例子。

#ifndef APP_H
#define APP_H
#include <QColor>
#include <QSize>
#include <QWindow>
#include <QRasterWindow>
#include <QPainter>
#include <QRect>
#include <QPaintEvent>
#include <QRegion>
#include <QList>
#include <QPolygon>
#include <QPoint>
#include <QResizeEvent>

class CustWindow : public QRasterWindow
{
    Q_OBJECT

public:
    CustWindow(QWindow *parent = nullptr);

protected:
    void paintEvent(QPaintEvent* event) override;
    void resizeEvent(QResizeEvent* event) override;

    // 窗口没了边框无法用常规操作,于是实现双击关闭窗口
    void mouseDoubleClickEvent(QMouseEvent *event) override;
};
#endif
CustWindow::CustWindow(QWindow* parent)
    :QRasterWindow::QRasterWindow(parent)
{
    setFlags(Qt::WindowType::FramelessWindowHint|Qt::WindowType::BypassWindowManagerHint);
    // 窗口位置和大小
    setGeometry(600, 500, 400, 400);
}

void CustWindow::paintEvent(QPaintEvent* event)
{
    QPainter p(this);
    p.fillRect(event->rect(), QColor("deeppink"));
    p.end();
}

void CustWindow::resizeEvent(QResizeEvent *event)
{
    QRegion rg0(QRect(QPoint(), event->size()));

    QList<QPoint> pt1 = {
        {15,16},
        {180, 300},
        {320, 300},
        {150, 57}
    };
    QPolygon pl1(pt1);
    QRegion rg1(pl1);

    QList<QPoint> pt2 = {
        {315, 20},
        {25, 160},
        {160, 320},
        {240, 150},
        {330, 30}
    };
    QPolygon pl2(pt2);
    QRegion rg2(pl2);

    QRegion rg3 = rg0 & (rg1 | rg2);
    setMask(rg3);
}

void CustWindow::mouseDoubleClickEvent(QMouseEvent *event)
{
    if(event->button() == Qt::LeftButton)
    {
        this->close();   // 关闭窗口
    }
}

调用setFlags方法时,用到了 WindowType::BypassWindowManagerHint 值。Windows 下没有影响,主要是针对 X11,去除第三方主题产生的窗口阴影。

在 resize 事件处理代码中,QPolygon 类用来构建多边形,通过 QList<QPoint> 对象来指定顶点列表。上面代码中是两个不规则图形并集后,再与窗口的矩形区域取交集。最后把这个区域外的内容都设置成了透明。

运行效果如下。

【Qt6】嵌套 QWindow

 

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

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

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

相关文章

  • 【Qt6】QStringList

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

    2024年02月06日
    浏览(27)
  • Qt5和Qt6的区别

    Qt4和Qt5的区别 之前有做过将项目从QT4迁移到QT5的操作,所以写了一篇QT4和Qt5的区别。在最近这一年接触过Qt6后,所以想要介绍一下Qt6和Qt5的区别,通过自己的试用感受和结合网上各路大佬的点拨,有了一个大概的了解。 各稳定版本: Qt4: 4.8.7 4.X 系列终结版本 Qt5 : 5.6 LTS 长期

    2024年01月18日
    浏览(44)
  • 一.QT QT6.5快速安装(Windows)

    本文仅适用于初学者参考!!! 如有错误和疑问请指出  点开 下载 打开命令行: 快捷键win+r 输入cmd 输入D:qt-unified-windows-x64-4.5.1-online.exe --mirror https://mirrors.ustc.edu.cn/qtproject(因为我的安装器下在D盘所以开头是D:,其他盘相同)                               

    2023年04月25日
    浏览(32)
  • Qt6.2教程——3.Qt信号和槽

    信号和槽是Qt中一个强大的特性,用于处理对象之间的通信。它们是一种事件处理机制,允许一个对象在某个事件发生时通知另一个对象。 定义 : 信号是一个QObject的成员函数,当某个特定事件发生时,它被自动调用。它可以与一个或多个槽关联。 声明 : 在Qt类的声明中,信号

    2024年02月10日
    浏览(35)
  • Qt6教程之一 Qt介绍及准备工作

    在正式开始之前,需要在自己电脑上面搭建好Qt的开发环境,本教程使用的Qt开发环境为Qt6.2 。 那话不多说,咋们开始做准备工作吧! 第一步:查看电脑硬件配置及操作系统 如果有一台较好配置的电脑,那么无疑用起来是最舒心的,推荐的最佳电脑配置: 由于Qt是为跨平台而

    2024年02月09日
    浏览(25)
  • Qt6入门教程 6:Qt元对象系统

    目录 一.什么是Qt元对象系统? 二.编译时Qt Creator偷摸做了哪些事情? 1.uic 2.rcc 3.moc Qt中的元对象系统(Meta-Object System)提供了对象间通信的信号和槽机制、运行时类型信息和动态属性系统。元对象系统是基于以下3个条件的: ●该类必须继承自QObject类; ●必须在类的私有声

    2024年01月18日
    浏览(44)
  • Qt6.2教程——7.QT常用控件QTextEdit

    QTextEdit 是 Qt 的一个用于编辑和显示纯文本和富文本的控件。它是功能强大且高度灵活的,可以用于实现多种任务,如文本编辑,数据表示,以及HTML的显示和编辑等。QTextEdit 支持富文本功能,这意味着它可以显示各种字体,颜色和文字格式。同时,QTextEdit 也支持文本搜索,

    2024年02月11日
    浏览(31)
  • Qt6.2教程——5.QT常用控件QLabel

    QLabel是Qt库中一个非常基础且重要的类。它主要用于在图形用户界面(GUI)中展示文本或图片。最常见的用法就是在窗口上显示一段文字或者标签,比如“用户名”,“密码”等等。QLabel继承自QFrame,因此它也可以具有框架。它能处理富文本格式,这意味着您可以改变部分文本的

    2024年02月10日
    浏览(31)
  • Qt6 c++教程2 Qt Creator简介

    Qt Creator是Qt自带的集成开发环境(IDE),用于跨平台应用程序开发。在本章中,您将学习Qt Creator集成开发环境的基础知识,并了解集成开发环境的用户界面 (UI)。我们还将了解如何在 Qt Creator中创建和管理项目。本Qt 模块包括使用Qt Creator开发一个简单的Qt应用程序、快捷方式

    2024年02月05日
    浏览(34)
  • Qt6之模型和视图

    MVC是Model-View-Controller,即 模型 (Model)、 视图 (View)、 控制器 (Controller)。 模型 :用于管理数据; 视图 :就是呈现在用户面前的界面外观,视图负责把模型中的数据显示给用户; 控制器 :用于处理用户在用户界面的输入; MVC本质上目的是数据处理和显示分离,以提高灵活性

    2024年02月15日
    浏览(27)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包