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

『 QT 』Hello World控件实现指南

文章目录

    • 输入框实现 "Hello world"
      • 用 Designer 实现
      • 用代码实现
    • 按钮实现 "Hello world"
      • 用 Designer 实现
        • 按钮添加点击处理
      • 用代码实现


输入框实现 “Hello world”

用 Designer 实现

  1. 创建一个Widget项目

  2. 双击.ui文件进入Designer设计模式

  3. 将左侧工具栏找到Input Widget分类并将需要的控件拖动至程序框内

  4. 在控件中文本写入编辑内容

    也可通过右侧的属性编辑区进行修改;

  5. 构建并运行

在使用Designer中添加/设计的控件一般是一XML的形式写进.ui(FromFile)文件中, 通过元编程的方式将XML转化为代码, 该项目所使用的框架是Widget框架, 因此在编译后项目中会存在一个ui_widget.h头文件, 在这个文件中可以看到使用Designer中添加的控件;

因此使用Designer添加的控件无需手动去设置链接对象树;


用代码实现

代码实现通常在使用框架的源文件中的构造函数中对控件进行编辑;

例如此处使用的是widget框架, 对应的需要再widget.cpp中的class Widget的构造函数中对控件进行编辑, 或者如果有一个子控件类继承了这个类, 则在这个派生类的构造函数中去设置控件;

#include "widget.h"
#include "ui_widget.h"
#include <QLineEdit> // 包含头文件 <QLineEdit>Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);QLineEdit* _edit = new QLineEdit(this); // 创建一个 QLineEdit 实例并指名父对象为 this_edit->setText("Hello World"); // 在 QLineEdit 中设置文本 "Hello World"
}Widget::~Widget()
{delete ui;
}

在这里的控件位于左上角, 本质上是没有设置控件在窗口的具体位置;


按钮实现 “Hello world”

用 Designer 实现

使用Designer实现与文本框的实现方式一致;

即拖动Buttons中的控件至UI界面完成实现;

构建后运行结果为如下:

但在这个按钮中点击是无反应的, 本质上是没有设置信号和槽;

  • 信号和槽

    信号和槽本质上是通过按钮对应的一些行为绑定对应的处理函数, 如当点击按钮后, 可能触发的是一个click事件, 这个事件会调用所绑定的处理函数从而进行一些变化;

    通常情况下载QT中使用connect()来绑定一个控件具体某个行为的处理函数;

    connect()socket中的connect()用途不同, 属于同名但不同作用和意义;

    需要注意的是, 槽并不是一个容器, 与可能抽象理解的凹槽不太一样;

    并不能抽象理解为这种槽;

    槽本身是一种函数, 全程为槽函数, 本质上是与信号通过connect()函数的绑定关系;

    硬要说的话可以这么说:

    槽函数就是普通的成员函数, 没有"空槽"的概念, 一个信号可以连接槽函数, 也可以不连接任何槽函数, 当连接槽函数时收到对应信号将会调用槽函数对信号进行处理, 若是不连接任何槽函数时将会忽略发送的信号;

以该例子来说, 所采用的控件为QPushButton, 该控件的信号通常有如下:

  • pressed()信号

    鼠标按下时触发;

    对应的事件处理函数是mousePressEvent();

  • clicked()信号

    鼠标松开时触发, 如果鼠标拖拽到按钮区域外再释放则不会触发;

    对应的事件处理函数是mouseReleaseEvent();

  • released()信号

    鼠标松开时触发, 按下后鼠标拖拽到按钮区域外再释放仍然会触发;

    对应的事件处理函数是mouseReleaseEvent();

  • toggled()信号

    设置setCheckable(true)后单击按钮才会触发该信号;

    一般用于多个按钮组成QButtonGroup(true)设置按钮间互斥;

    其中toggled()信号主要关心的是按钮状态的变化, 而不是按钮是否被点击;

信号和槽本质上是这样的, 假设信号是clicked()信号, 当一个按钮被单击(单击包含点击和释放)后, 这个单击本身就是一个事件, 按下和释放时将会自动调用对应的处理函数(按下的处理函数为mousePressEvent(), 释放为mouseReleaseEvent()), 判断按下和释放的时间(两个事件处理的时间), 按下和释放是否在同一控件区域内, 按下后鼠标是否移出按钮区域等条件来向控件发送对应的信号, 当发送clicked()信号后, 由于connect()绑定了对应信号的槽函数, 将会调用对应的信号处理函数进行一个处理;


按钮添加点击处理

上文提到, 若是需要使用点击需要设置信号和槽, 即通过connect()函数来绑定对应信号的信号处理函数(槽函数);

  • connect()函数

    经过版本的迭代, QT支持两种语法来实现连接信号与槽;

    这里主要演示的是新语法;

    QObject::connect(sender, &SenderType::signal, receiver, &ReceiverType::slot, Qt::ConnectionType type = Qt::AutoConnection);
    

    参数解释如下:

    • sender

      发送信号的对象指针;

      如果控件对象是通过Qt Designer来创建的, 那么需要使用ui -> button_name的方式, 即通过ui对象指向对应指针的方式来进行传参;

      否则可以直接传入一个QObject子类对象, 如使用代码创建控件时可以直接将控件变量名直接传入(前提是控件对象是new出来的);

    • &SenderType::signal

      发送者类型的信号成员函数地址;

      表示槽函数对应的信号种类, 可能为pressed, clicked等信号, 信号一定要匹配对应的控件对象类型;

    • receiver

      接收信号的对象指针;

      表示谁来处理这个信号, 通常为槽函数的拥有者, 需要传入该对象的指针;

      当然如果槽函数是全局函数, lamdba表达式或是静态成员函数, receiver可以是任意对象, 甚至是nullptr, 因为本质上并不是由receiver来调用这些函数, receiver本质上是管理线程的生命周期, 即当信号被发射后Qt内部将会形成一个事件或是直接调用槽(取决于第五个参数的连接方式), 而调用槽时所在的线程是不同的, 当槽位上述几种函数时分为两种情况:

      1. receivernullptr

        槽函数在信号发射的线程中执行;

      2. receiver不为nullptr

        槽函数在receiver所在线程执行(具体方式由第五个参数Qt::ConnectionType type决定);

    • &ReceiverType::slot

      槽函数的函数指针, 可以是成员函数, 全局函数, 静态成员函数或者是Lamdba表达式;

    • Qt::ConnectionType type = Qt::AutoConnection

      连接情况分为以下几种:

      1. Qt::DirectConnection

        槽函数在信号发射线程立即执行;

      2. Qt::QueuedConnection

        槽函数在receiver所在线程的事件循环中执行;

      3. Qt::AutoConnection

        Qt自动判断(同线程情况下为DirectConnection, 不同线程为QueuedConnection);

      4. Qt::BlockingQueuedConnection

        类似Queued, 但发送线程会阻塞等待;

在之前的操作中已经创建了一个QPushButton按钮控件对象, 该按钮使用Designer创建, 因此在使用connect()函数时sender需要通过ui对象指向该控件对象的objectName(本质上就是控件指针变量名), 此处变量名为pushButton_1;

在此之前需要一个信号处理函数(槽函数), 这里的槽函数选择在Widget中创建对应的成员函数, 同样在widget.h中进行声明, 在widget.cpp中进行实现;

本次实现为点击按钮进行文本的转换, 单击信号为clicked信号;

////////////////////////////////////////
/////////////*  widget.h  */////////////
////////////////////////////////////////QT_BEGIN_NAMESPACE
namespace Ui {
class Widget;
}
QT_END_NAMESPACEclass Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);void handleClick_1(); // 槽函数声明~Widget();private:Ui::Widget *ui;
};////////////////////////////////////////
/////////////* widget.cpp */////////////
////////////////////////////////////////Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);connect(ui->pushButton_1, &QPushButton::clicked, this, &Widget::handleClick_1); // 通过 connect 函数来绑定信号与槽
}void Widget::handleClick_1(){ // 槽函数定义// 判断 pushButton_1 控件中的文本 是否为 "Click me!" // 是则改变文本为 "Hello world"if(ui->pushButton_1->text() == QString("Click me!")){ ui->pushButton_1->setText("Hello world");}else{// 否则改变文本为 "Click me!"ui->pushButton_1->setText("Click me!");}
}Widget::~Widget()
{delete ui;
}

在这段代码中的Widget::Widget(QWidget *parent)构造函数中的connect()函数中第一个参数采用了ui->pushButton_1进行传参, 这里需要传的参数是信号发送的控件指针;

在项目构建完毕后, 可以从项目结构里的ui_widget.h文件中可以看到;

通过构建后, class Ui_Widget类中出现了一个QPushButton *pushButton_1的成员变量;

该成员则是所传的参数;

一般情况下当使用QtCreator中的Designer创建控件对象后, 当保存.ui文件时, QtCreator将会分析.uixml文件, 并在ui_xxx.h中补全相应代码;

因此可以直接使用ui->的方式对Designer创建的控件对象进行指向;


用代码实现

此次用代码实现的按钮Button功能与上文相同, 同样为点击前文本为"Click me!", 点击后为"Hello world";

通常情况下, 所创建的控件可能需要在槽中传入或是调用自己的成员, 而指针变量是局部变量, 当构造函数结束后这个局部变量(指针变量)的生命周期也会随之结束, 因此无法再槽中调用这个指针变量, 而较好的解决办法是将控件对象作为框架的成员变量进行创建定义;

class Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);void handleClick();~Widget();private:Ui::Widget *ui;QPushButton *myButton;
};

通常也支持推荐使用这种方式创建, 这样既可以对其进行更好的生命周期管理, 也能增加访问便利性;

通常情况下若是将控件对象作为成员函数, 通常建议在类中声明, 在构造函数中的初始化列表或是构造函数函数体内进行初始化;

Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget), myButton(new QPushButton(this))
{ui->setupUi(this);myButton->setText("Click me!");connect(myButton, &QPushButton::clicked, this, &Widget::handleClick);
}void Widget::handleClick(){if(myButton->text() == QString("Click me!")){myButton->setText("Hello world");}else{myButton->setText("Click me!");}
}Widget::~Widget()
{delete ui;
}
http://www.dtcms.com/a/469820.html

相关文章:

  • 【CF】Day148——Codeforces Round 1057 (Div. 2) CD (非退化凸多边形的分类讨论 | 破环成链动态规划)
  • 网站建设教程金旭亮wordpress自动加p标签
  • 使用C#代码将ODT转换为PDF文件
  • 【网络编程】详解 IP 协议:报头字段、路由器功能、网段划分和分片传输
  • 大模型微调 SFTTrainer 数据处理与训练器配置解析(116)
  • gtest简单应用
  • 访答知识库,企业知识库,访答浏览器,Al编辑器,RAG,Pdf转word。个人知识库,访答RAG,云知识库,私有知识库……
  • 通过企业画册宣传_网络网站建设_新闻媒体合作等方式_企业营销网站制作
  • BERT相关知识自测
  • 【完整源码+数据集+部署教程】 真菌孢子图像分割系统源码&数据集分享 [yolov8-seg-convnextv2等50+全套改进创新点发刊_一键训练
  • 遵义市网站制作如何申请域名网站注册
  • GitHub 热榜项目 - 日榜(2025-10-11)
  • MySQL数据库之DBA命令
  • 4.打造个人Z-Library镜像
  • CoRL-2025 | 物体相对控制赋能具身导航!ObjectReact:学习用于视觉导航的物体相对控制
  • 长春seo网站优化做企业网站接单
  • word超链接网站怎么做网站建设网页设计网站模板
  • spring boot 整合 activiti 教程
  • 免费网站电视剧下载不支持下载的视频怎么保存下来
  • 接口自动化测试流程、工具与实践
  • 【C++继承】深入浅出C++继承机制
  • Mysql杂志(三十一)——Join连接算法与子查询、排序优化
  • HashMap - 底层原理
  • Python第二次作业
  • Vspy使用教程
  • 通用网站模板网站备案要幕布照
  • 网站三要素关键词 描述怎么做青海项目信息网官网
  • JavaScript学习笔记(二十八):JavaScript性能优化全攻略
  • mooc自动互评脚本笔记---2025年10月11日
  • 什么是语言模型