从零开始的Qt开发指南:(五)Qt 常用控件之 QWidget(上):解锁 Qt 界面开发的核心基石

目录

前言

[一、Qt 控件概述:图形界面的 "积木块"](#一、Qt 控件概述:图形界面的 “积木块”)

[1.1 什么是控件?](#1.1 什么是控件?)

[1.2 Qt 控件的 "家族体系"](#1.2 Qt 控件的 “家族体系”)

[1.3 控件体系的发展历程](#1.3 控件体系的发展历程)

[二、QWidget 核心属性:掌控控件的 "生杀大权"](#二、QWidget 核心属性:掌控控件的 “生杀大权”)

[2.1 核心属性概览](#2.1 核心属性概览)

[2.2 enabled:控件的 "启用 / 禁用" 开关](#2.2 enabled:控件的 “启用 / 禁用” 开关)

[2.2.1 核心 API](#2.2.1 核心 API)

[2.2.2 代码示例 1:创建禁用状态的按钮](#2.2.2 代码示例 1:创建禁用状态的按钮)

[2.2.3 代码示例 2:动态切换控件的启用状态](#2.2.3 代码示例 2:动态切换控件的启用状态)

[2.3 geometry:控件的 "位置与尺寸" 管家](#2.3 geometry:控件的 “位置与尺寸” 管家)

[2.3.1 核心 API](#2.3.1 核心 API)

[2.3.2 代码示例 1:控制按钮的位置移动](#2.3.2 代码示例 1:控制按钮的位置移动)

[2.3.3 geometry 与 frameGeometry 的区别](#2.3.3 geometry 与 frameGeometry 的区别)

[2.4 windowTitle:给窗口加个 "名字牌"](#2.4 windowTitle:给窗口加个 “名字牌”)

[2.4.1 核心 API](#2.4.1 核心 API)

[2.4.2 代码示例:设置窗口标题](#2.4.2 代码示例:设置窗口标题)

[2.5 windowIcon:给窗口换个 "头像"](#2.5 windowIcon:给窗口换个 “头像”)

[2.5.1 核心 API](#2.5.1 核心 API)

[2.5.2 代码示例 1:通过绝对路径设置图标](#2.5.2 代码示例 1:通过绝对路径设置图标)

[2.5.3 代码示例 2:通过 Qt 资源文件(qrc)设置图标](#2.5.3 代码示例 2:通过 Qt 资源文件(qrc)设置图标)

[2.6 windowOpacity:给窗口加个 "透明滤镜"](#2.6 windowOpacity:给窗口加个 “透明滤镜”)

[2.6.1 核心 API](#2.6.1 核心 API)

[2.6.2 代码示例:动态调整窗口透明度](#2.6.2 代码示例:动态调整窗口透明度)

总结


前言

在 Qt 的 GUI 开发世界里,QWidget绝对是当之无愧的 "老大哥"。它是所有可视化控件的基类,就像盖房子的地基,不管是按钮、输入框还是复杂的表格,统统都继承自它。想要玩转 Qt 界面开发,不把QWidget的核心属性和用法啃透,那可真是寸步难行。今天这篇文章,就带大家从零开始,深挖QWidget的控件概述和核心属性(enabled、geometry、windowTitle、windowIcon、windowOpacity),用最通俗的语言和实战代码,把这些知识点揉碎了讲清楚!下面就让我们正式开始吧!


一、Qt 控件概述:图形界面的 "积木块"

1.1 什么是控件?

在 Qt 中,**Widget(控件)**是构成图形化界面的基本要素,英文原义是 "小部件",咱们可以把它理解成搭建界面的 "积木块"。想象一下,你打开一个软件,看到的按钮、输入框、下拉菜单、滚动条,甚至是树形列表,这些都是 Qt 中的控件。

比如一个简单的 Qt 窗口程序,里面可能包含这些常见控件:

  • 按钮(PushButton):点击触发操作;
  • 单行输入框(Line Edit):输入文字;
  • 多行输入框(Text Edit):输入大段文本;
  • 下拉框(Combo Box):选择预设选项;
  • 滚动条(Scroll Bar):浏览超出界面的内容;
  • 树形视图(Tree View)列表视图(List View):展示结构化数据。

这些控件各司其职,组合在一起就形成了我们日常使用的软件界面。下面是一个最基础的 Qt 窗口程序示例,仅需几行代码就能创建一个包含QWidget的窗口:

cpp 复制代码
#include "widget.h"
#include <QApplication>

int main(int argc, char *argv[]) {
    QApplication a(argc, argv);
    Widget w;
    w.show();
    return a.exec();
}

这段代码创建了一个 Qt 应用程序对象QApplication,实例化了自定义的Widget(继承自QWidget),并通过**show()方法显示窗口,最后通过exec()**进入应用程序的事件循环。

1.2 Qt 控件的 "家族体系"

Qt 作为成熟的 GUI 开发框架,内置了海量常用控件,在Qt Designer 中我们能直观看到这些控件的分类:

  • 按钮类:Push Button、Radio Button、Check Box 等;
  • 输入类:Line Edit、Text Edit、Spin Box 等;
  • 视图类:List View、Tree View、Table View 等;
  • 容器类:Group Box、Tab Widget、Scroll Area 等。

除了现成的控件,Qt 还支持自定义控件。当内置控件满足不了需求时,我们可以基于现有控件扩展,甚至从零打造全新的控件,这让 Qt 的界面开发灵活性拉满。

1.3 控件体系的发展历程

控件并非 Qt 独有,而是 GUI 开发的通用概念,它的发展大致分为三个阶段:

  1. 无控件时代 :需要通过绘图 API 手动绘制按钮、输入框,代码编写极其繁琐,比如早期文曲星的 Lava 平台开发;
  2. 粗略控件时代 :仅提供按钮、输入框、单选框等最基础的控件,功能简单,比如 HTML 的原生控件;
  3. 完整控件体系时代 :覆盖 GUI 开发的大部分场景,Qt、MFC、Android SDK、前端 UI 库(如 Element-UI)都属于这一阶段,控件丰富度和美观度都有了质的飞跃。

对比前端的 Element-UI,Qt 自带控件的颜值可能稍逊一筹,但胜在跨平台性和功能的稳定性,是桌面端 GUI 开发的首选之一。

二、QWidget 核心属性:掌控控件的 "生杀大权"

QWidget是所有 Qt 控件的父类,它包含了整个控件体系中最通用的属性。这些属性既可以在 Qt Designer 中可视化修改,也能通过代码动态调整,是我们控制控件外观和行为的核心。接下来,我们逐个拆解最常用的核心属性。

2.1 核心属性概览

QWidget的属性多达数十个,涵盖了控件的可用性、位置尺寸、外观样式、交互行为等方方面面。下表列出了后续要重点讲解的属性及其作用:

属性名 作用
enabled 设置控件是否可使用,true 为可用,false 为禁用
geometry 控件的位置和尺寸,包含 x、y、width、height 四个参数
windowTitle 设置顶层 Widget 的窗口标题
windowIcon 设置顶层 Widget 的窗口图标
windowOpacity 设置窗口的透明度,取值 0.0(全透明)~1.0(完全不透明)

这些属性是 Qt 界面开发的 "高频考点",掌握它们就能轻松实现控件的基础控制。

2.2 enabled:控件的 "启用 / 禁用" 开关

enabled属性决定了控件是否能响应用户的交互操作。当控件被禁用(enabled = false)时,不仅无法接收点击、输入等事件,外观上还会变成灰色,给用户直观的视觉反馈。

2.2.1 核心 API

API 说明
isEnabled() 获取控件的可用状态,返回 bool 值
setEnabled(bool) 设置控件的可用状态,true 启用,false 禁用

2.2.2 代码示例 1:创建禁用状态的按钮

我们先创建一个默认禁用的按钮,看看效果:

运行程序后,按钮会显示为灰色,无法被点击,这就是enabled属性的基础用法。

2.2.3 代码示例 2:动态切换控件的启用状态

实际开发中,我们经常需要根据业务逻辑动态切换控件的状态。比如通过一个按钮来控制另一个按钮的启用 / 禁用:

  1. 在 Qt Designer 中拖入两个按钮,objectName分别为pushButton(目标按钮)和pushButton_enable(切换按钮);
  2. 编写切换按钮的点击事件槽函数:
cpp 复制代码
//widget.cpp
#include "ui_widget.h"
#include <QDebug>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
}

Widget::~Widget()
{
    delete ui;
}


void Widget::on_pushButton_clicked()
{
    qDebug() << "执行了槽函数";
}

void Widget::on_pushButton_enable_clicked()
{
    //切换第一个按钮的禁用状态
    //1.先获取到第一个按钮当前的可用状态
    bool enable = ui->pushButton->isEnabled();
    if(enable)
    {
        ui->pushButton->setEnabled(false);
    }
    else
    {
        ui->pushButton->setEnabled(true);
    }
}

运行程序后,点击 "切换可用状态",目标按钮会在启用(可点击)和禁用(灰色不可点)之间切换,控制台会输出状态变化的日志。

2.3 geometry:控件的 "位置与尺寸" 管家

geometry属性是控件位置和尺寸的 "集合体",它包含四个核心参数:

  • x:控件左上角的横坐标(以父控件左上角为原点);
  • y:控件左上角的纵坐标;
  • width:控件的宽度;
  • height:控件的高度。

Qt 采用左手坐标系,原点在父控件的左上角,x 轴向右递增,y 轴向下递增,这一点一定要记牢!

2.3.1 核心 API

API 说明
geometry() 获取控件的位置和尺寸,返回 QRect 对象(包含 x、y、width、height)
setGeometry(QRect) 通过 QRect 对象设置控件位置和尺寸
setGeometry(int x, int y, int width, int height) 直接通过四个参数设置位置和尺寸

2.3.2 代码示例 1:控制按钮的位置移动

我们实现一个简单的功能:通过四个方向按钮控制目标按钮的上下左右移动。

  1. 在 Qt Designer 中拖入五个按钮,**objectName**分别为:
    • pushButton_target:目标按钮;
    • pushButton_up:向上按钮;
    • pushButton_down:向下按钮;
    • pushButton_left:向左按钮;
    • pushButton_right:向右按钮。
  2. 编写方向按钮的点击事件槽函数:
cpp 复制代码
// widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include <QDebug>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
}

Widget::~Widget()
{
    delete ui;
}


void Widget::on_pushButton_up_clicked()
{
    //获取到target本身的geometry
    QRect rect = ui->pushButton_target->geometry();
    qDebug() << rect;
//    rect.setY(rect.y() - 5);
//    ui->pushButton_target->setGeometry(rect);

    ui->pushButton_target->setGeometry(rect.x(), rect.y() - 5, rect.width(), rect.height());
}

void Widget::on_pushButton_down_clicked()
{
    QRect rect = ui->pushButton_target->geometry();
    qDebug() << rect;
//    rect.setY(rect.y() + 5);
//    ui->pushButton_target->setGeometry(rect);

    ui->pushButton_target->setGeometry(rect.x(), rect.y() + 5, rect.width(), rect.height());
}

void Widget::on_pushButton_left_clicked()
{
    QRect rect = ui->pushButton_target->geometry();
    qDebug() << rect;
//    rect.setX(rect.x() - 5);
//    ui->pushButton_target->setGeometry(rect);

    ui->pushButton_target->setGeometry(rect.x() - 5, rect.y(), rect.width(), rect.height());
}

void Widget::on_pushButton_right_clicked()
{
    QRect rect = ui->pushButton_target->geometry();
    qDebug() << rect;
//    rect.setX(rect.x() + 5);
//    ui->pushButton_target->setGeometry(rect);

    ui->pushButton_target->setGeometry(rect.x() + 5, rect.y(), rect.width(), rect.height());
}

运行程序后,点击方向按钮,目标按钮就会以 5 个像素为步长移动。

2.3.3 geometry 与 frameGeometry 的区别

在 Qt 中,当Widget作为顶层窗口(带有标题栏、最小化 / 最大化 / 关闭按钮)时,geometryframeGeometry会有差异:

  • geometry不包含窗口边框(title bar),仅计算客户区的位置和尺寸;
  • frameGeometry包含窗口边框,计算整个窗口的位置和尺寸。

我们通过代码验证一下:

cpp 复制代码
// widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include <QDebug>
#include <QPushButton>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    QPushButton* button = new QPushButton(this);
    button->setText("按钮");
    button->move(100, 100);

    connect(button, &QPushButton::clicked, this, &Widget::handle);
}

Widget::~Widget()
{
    delete ui;
}

void Widget::handle()
{
    QRect rect1 = this->geometry();
    QRect rect2 = this->frameGeometry();
    qDebug() << rect1;
    qDebug() << rect2;
}

运行程序后,构造函数中两者的输出一致,而点击按钮后,frameGeometry的宽度和高度会比geometry大(包含了窗口边框)。

2.4 windowTitle:给窗口加个 "名字牌"

windowTitle属性用于设置顶层Widget的窗口标题,也就是窗口左上角显示的文字。这个属性仅对顶层窗口有效,子控件设置该属性不会有任何效果。

2.4.1 核心 API

API 说明
windowTitle() 获取窗口标题,返回 QString
setWindowTitle(const QString& title) 设置窗口标题

2.4.2 代码示例:设置窗口标题

运行程序后,窗口的标题栏会显示 "这是窗口标题"。我们添加了一个按钮,点击后就会修改标题为"通过按钮设置窗口标题"。

2.5 windowIcon:给窗口换个 "头像"

windowIcon属性用于设置顶层Widget的窗口图标,这个图标会显示在窗口左上角、任务栏中,是窗口的 "视觉标识"。和windowTitle一样,该属性仅对顶层窗口有效。

2.5.1 核心 API

API 说明
windowIcon() 获取窗口图标,返回 QIcon 对象
setWindowIcon(const QIcon& icon) 设置窗口图标

2.5.2 代码示例 1:通过绝对路径设置图标

cpp 复制代码
// widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include <QIcon>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    // 创建图标对象,加载本地图片(D盘的anno.jpg)
    QIcon icon("d:/anno.jpg");
    // 设置窗口图标
    this->setWindowIcon(icon);
}

Widget::~Widget()
{
    delete ui;
}

注意:Windows 系统中,路径分隔符可以用**/或转义后的\**(如"d:\\anno.jpg"),推荐使用/避免转义错误。

2.5.3 代码示例 2:通过 Qt 资源文件(qrc)设置图标

直接使用绝对路径存在隐患:如果用户电脑上没有该路径的图片,图标就会加载失败。Qt 提供了qrc 资源文件机制,将图片打包到程序中,实现 "路径无关" 的资源管理。

  1. 创建 qrc 资源文件

    • 在 Qt Creator 中右键项目 → 新建文件 → Qt → Qt Resource File,命名为resource.qrc
    • 打开resource.qrc,点击 "Add Prefix" 添加前缀(如/),再点击 "Add Files" 添加图片文件(将 anno.jpg 复制到项目目录下)。
  2. 通过 qrc 设置图标

    cpp 复制代码
    // widget.cpp
    #include "widget.h"
    #include "ui_widget.h"
    #include <QIcon>
    
    Widget::Widget(QWidget *parent)
        : QWidget(parent)
        , ui(new Ui::Widget)
    {
        ui->setupUi(this);
        // 从qrc资源中加载图标(:/表示资源路径,rose.jpg是资源文件名)
        QIcon icon(":/anno.jpg");
        this->setWindowIcon(icon);
    }
    
    Widget::~Widget()
    {
        delete ui;
    }

Qt 会把 qrc 中的资源编译成 C++ 代码,打包到可执行文件中,这样无论程序放到哪个目录,都能正常加载图标。如下所示:

2.6 windowOpacity:给窗口加个 "透明滤镜"

windowOpacity属性用于设置窗口的透明度,取值范围是 0.0(完全透明)到 1.0(完全不透明)。通过这个属性,我们可以实现窗口的淡入淡出、半透明等炫酷效果。

2.6.1 核心 API

API 说明
windowOpacity() 获取窗口透明度,返回 float 值
setWindowOpacity(float n) 设置窗口透明度,n∈[0.0,1.0]

2.6.2 代码示例:动态调整窗口透明度

我们实现一个功能:通过两个按钮分别增加和减少窗口的透明度。

  1. 在 Qt Designer 中拖入两个按钮,objectNamepushButton_add(增加透明度)和pushButton_sub(减少透明度);

  2. 编写按钮的点击事件槽函数:

    cpp 复制代码
    // widget.cpp
    
    #include "widget.h"
    #include "ui_widget.h"
    #include <QDebug>
    
    Widget::Widget(QWidget *parent)
        : QWidget(parent)
        , ui(new Ui::Widget)
    {
        ui->setupUi(this);
    }
    
    Widget::~Widget()
    {
        delete ui;
    }
    
    
    void Widget::on_pushButton_add_clicked()
    {
        float opacity = this->windowOpacity();
        if(opacity >= 1.0)
        {
            return;
        }
        qDebug() << opacity;
        opacity += 0.1;
        this->setWindowOpacity(opacity);
    }
    
    void Widget::on_pushButton_sub_clicked()
    {
        float opacity = this->windowOpacity();
        if(opacity <= 0.0)
        {
            return;
        }
        qDebug() << opacity;
        opacity -= 0.1;
        this->setWindowOpacity(opacity);
    }

运行程序后,点击 "减少透明度" 按钮,窗口会逐渐变透明;点击 "增加透明度" 按钮,窗口会逐渐恢复不透明。需要注意的是,C++ 中的 float 类型存在精度误差,比如 1.0 - 0.1 的结果并非严格等于 0.9,这是正常现象。


总结

本文我们从 Qt 控件的基本概念入手,详细讲解了QWidget的核心属性:enabled控制控件的可用性、geometry管理控件的位置和尺寸、windowTitle设置窗口标题、windowIcon定制窗口图标、windowOpacity调整窗口透明度。这些属性是 Qt 界面开发的基础,掌握它们就能实现控件的基础控制和窗口的个性化定制。

在下一篇文章中,我们会继续讲解QWidget的其他核心属性(如 cursor、font、toolTip 等),以及按钮类、显示类等常用控件的用法。关注我,一起解锁 Qt 界面开发的更多技能!

注:本文的代码示例均基于 Qt 5.14.2 版本编写,不同 Qt 版本的 API 可能略有差异,但核心用法一致。如果大家在学习过程中有任何问题,欢迎在评论区留言交流~

相关推荐
wjs20241 小时前
SQLite 视图
开发语言
q***44811 小时前
java进阶--多线程学习
java·开发语言·学习
艾斯比的日常1 小时前
Neo4j 完全指南:从核心特性到 Java 实战(附企业级应用场景)
java·开发语言·neo4j
后端小张1 小时前
【JAVA 进阶】深入探秘Netty之Reactor模型:从理论到实战
java·开发语言·网络·spring boot·spring·reactor·netty
柠石榴2 小时前
go-1 模型
开发语言·后端·golang
sulikey2 小时前
深入讲解:什么是 RAII(资源获取即初始化)——原理、实现、面试常考点与实战示例
c++·面试·智能指针·raii·shared_ptr·auto_ptr·资源获取即初始化
q***d1732 小时前
Rust在网络中的协议栈
开发语言·网络·rust
艾莉丝努力练剑2 小时前
【Git:多人协作】Git多人协作实战:从同分支到多分支工作流
服务器·c++·人工智能·git·gitee·centos·项目管理
星释2 小时前
Rust 练习册 88:OCR Numbers与光学字符识别
开发语言·后端·rust