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

QT(2)

二、UI入门​

​1、QWidget类(熟悉)​

QWidget类是Qt中所有用户界面组件的基类。窗口和控件(如按钮、标签等)都直接或间接继承自它。它提供了组件最基础的特性,如几何形状、布局、事件处理等。

​常用属性与方法:​

属性/方法类型/签名说明
​x : const int​属性 (只读)组件在其父组件坐标系中的​​横坐标​​,以左上角为定位点。横轴零点在父组件客户区最左边,正方向向右。​​注意:位置包含窗口边框​​。
​y : const int​属性 (只读)组件在其父组件坐标系中的​​纵坐标​​,以左上角为定位点。纵轴零点在父组件客户区最上边,正方向向下。​​注意:位置包含窗口边框​​。
​void move(int x, int y)​方法将组件移动到新的位置(x, y)。这是修改组件位置的常用方法。
​width : const int​属性 (只读)组件的​​宽度​​,​​不包含边框​​。
​height : const int​属性 (只读)组件的​​高度​​,​​不包含边框​​。
​void resize(int w, int h)​方法修改组件的宽度和高度。

​示例:在构造函数中设置窗口属性​

// dialog.cpp
#include "dialog.h"Dialog::Dialog(QWidget *parent): QDialog(parent) // 调用父类构造函数
{// 移动窗口到屏幕坐标(200, 200)的位置move(200, 200);// 设置窗口客户区的宽度为200像素,高度为600像素resize(200, 600);// 使用样式表设置窗口背景颜色为红色setStyleSheet("background-color:red");
}Dialog::~Dialog()
{// 析构函数
}
​2、添加子组件(掌握)​

空的窗口没什么用,我们通常需要向其中添加各种组件(如按钮、文本框等)来实现交互功能。这些组件需要​​在父窗口的构造函数中创建​​,并指定父对象(通常用 this),以确保父窗口析构时能自动销毁它们,避免内存泄漏。

​示例:添加按钮并设置样式​

​dialog.h (头文件)​

#ifndef DIALOG_H
#define DIALOG_H#include <QDialog>
#include <QDebug>
#include <QPushButton> // 包含QPushButton的头文件// 定义一个按钮的样式宏(可选,便于管理和复用)
#define QPushButton_STYLE (QString("\
QPushButton {\font-family: Microsoft Yahei;\font-size: 20pt;\color: white;\background-color: rgb(14, 150, 254);\border-radius: 8px;\
}\
QPushButton:hover {\background-color: rgb(100, 137, 112);\
}\
QPushButton:pressed {\background-color: rgb(14, 135, 10);\padding-left: 3px;\padding-top: 3px;\
}"))class Dialog : public QDialog
{Q_OBJECT // Qt元对象系统宏,必须包含private:QPushButton *btn; // 声明一个指向按钮的指针public:Dialog(QWidget *parent = nullptr);~Dialog();
};#endif // DIALOG_H

​dialog.cpp (源文件)​

#include "dialog.h"Dialog::Dialog(QWidget *parent): QDialog(parent)
{// 设置主窗口大小resize(500, 500);// 创建按钮对象:"你好"是按钮文本,this指定父对象为当前窗口btn = new QPushButton("你好", this);// 将按钮移动到相对父窗口(50, 250)的位置btn->move(50, 250);// 应用预定义的样式表btn->setStyleSheet(QPushButton_STYLE);
}Dialog::~Dialog()
{// 由于btn是父窗口的子组件,通常Qt会自动销毁它。// 但显式delete也是一个好习惯,尤其是在复杂项目中。delete btn;
}

​配色网站推荐:​

  • ColorPicker​​: http://tools.jb51.net/static/colorpicker/
  • Color Palettes​​: https://colors.muz.li/

​三、信号槽(重点)​

​1、概念​

信号槽是Qt的核心机制,用于对象间的通信,是一种类型安全且松耦合的“回调”。

  • 信号 (Signal)​​:由对象在特定事件发生时​​发射​​的通知(例如,按钮被点击时发射 clicked() 信号)。
  • 槽 (Slot)​​:普通的成员函数,用于​​响应​​特定的信号。
  • 连接 (Connection)​​:使用 QObject::connect() 函数建立信号与槽的关联。

​两个先决条件​

  1. 通信的对象必须直接或间接继承自 QObject
  2. 类声明中必须包含 Q_OBJECT 宏。
​2、函数原型​

connect 函数的基本形式如下:

// 参数1:sender,发送信号的对象指针
// 参数2:signal,发送的信号(使用 SIGNAL() 宏)
// 参数3:receiver,接收信号的对象指针
// 参数4:method,接收的槽函数(使用 SLOT() 宏)
// 返回值:QMetaObject::Connection,可用于后续断开连接
QMetaObject::Connection QObject::connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method);

​第五个参数 (Qt::ConnectionType) ​​:
connect 函数还有一个可选的第五个参数 type,用于指定连接方式,默认为 Qt::AutoConnection

连接类型含义
​Qt::AutoConnection​​ (默认)自动决定。如果发送者和接收者在同一线程,等同于 DirectConnection;否则等同于 QueuedConnection
​Qt::DirectConnection​直接连接。信号发射后,槽函数​​立即​​在​​发送者线程​​中被调用。
​Qt::QueuedConnection​队列连接。信号发射后,槽函数会被放入​​接收者线程的事件循环​​中,等待​​稍后​​在接收者线程中被调用。用于跨线程通信

2

​Qt::BlockingQueuedConnection​阻塞队列连接。类似 QueuedConnection,但​​发送者线程会阻塞​​,直到接收者线程的槽函数执行完毕。注意:发送者和接收者不能在同一线程。
​Qt::UniqueConnection​唯一连接。可以与其他类型按位或组合使用,确保相同的信号和槽只会被连接一次,防止重复连接。
​3、实现​
​3.1 自带信号 → 自带槽​

最简单的方式,使用Qt内置的信号和槽。
​示例:点击按钮,关闭窗口​

// dialog.cpp
#include "dialog.h"Dialog::Dialog(QWidget *parent): QDialog(parent)
{resize(500, 500);btn = new QPushButton("关闭", this);btn->move(200, 250);// 连接:按钮的clicked信号 -> 窗口的close槽connect(btn, SIGNAL(clicked()), this, SLOT(close()));
}
​3.2 自带信号 → 自定义槽​

最常用的方式,槽函数需要开发者自己声明和实现。
​示例:点击按钮,移动窗口并打印坐标​
​dialog.h​

// ... 其他代码同上 ...
class Dialog : public QDialog
{Q_OBJECT
// ... 其他代码同上 ...
private slots: // 声明自定义槽函数(私有槽)void mySlot(); // 槽函数
};

​dialog.cpp​

// ... 构造函数和按钮创建同上 ...connect(btn, SIGNAL(clicked()), this, SLOT(mySlot()));
}// 实现自定义槽函数
void Dialog::mySlot()
{int currentX = x(); // 获取当前x坐标int currentY = y(); // 获取当前y坐标move(currentX + 10, currentY + 10); // 移动窗口qDebug() << "New position:" << currentX + 10 << currentY + 10; // 打印新坐标
}
​3.3 自定义信号​

信号只需声明,无需实现(定义),使用 emit 关键字发射。
​示例:通过自定义信号间接关闭窗口​
​dialog.h​

// ... 其他代码同上 ...
class Dialog : public QDialog
{Q_OBJECT
// ... 其他代码同上 ...
signals: // 信号声明区域void mySignal(); // 自定义信号
private slots:void mySlot(); // 槽函数,用于响应按钮点击并发射自定义信号
};

​dialog.cpp​

// ... 构造函数 ...connect(btn, SIGNAL(clicked()), this, SLOT(mySlot()));// 连接:自定义信号mySignal -> 窗口的close槽connect(this, SIGNAL(mySignal()), this, SLOT(close()));
}void Dialog::mySlot()
{emit mySignal(); // 发射自定义信号
}
​4、信号槽传参​

信号和槽都可以带参数,参数类型必须兼容,且信号的参数个数可以​​多于​​槽的参数个数,但反之不行。
​示例:点击按钮,按钮文字显示点击次数​
​dialog.h​

// ... 其他代码同上 ...
class Dialog : public QDialog
{Q_OBJECT
// ... 其他代码同上 ...
public slots:void mySlot();void mySlot2(int count); // 带参数的槽
signals:void mySignal(int count); // 带参数的信号
};

​dialog.cpp​

// ... 构造函数 ...connect(btn, SIGNAL(clicked()), this, SLOT(mySlot()));connect(this, SIGNAL(mySignal(int)), this, SLOT(mySlot2(int)));
}void Dialog::mySlot()
{static int count = 0; // 静态变量记录点击次数count++;emit mySignal(count); // 发射信号,并传递count值
}void Dialog::mySlot2(int count)
{// 将整数转换为字符串并设置为按钮文本btn->setText(QString::number(count));
}

​传递自定义类型​​:如果信号槽需要传递自定义数据类型(如结构体或类),则该类型需要使用 qRegisterMetaType() 进行注册,才能在不同线程间安全传递(同一线程内有时可以不注册,但建议总是注册)。

​5、对应关系​
​5.1 一对多​

一个信号可以连接多个槽函数。信号发射时,​​槽函数的调用顺序是不确定的​​。

connect(button, SIGNAL(clicked()), this, SLOT(slot1()));
connect(button, SIGNAL(clicked()), this, SLOT(slot2()));
connect(button, SIGNAL(clicked()), this, SLOT(slot3()));
// 点击按钮,slot1, slot2, slot3 都会被调用(顺序不确定)
​5.2 多对一​

多个信号可以连接同一个槽函数。在槽函数中,可以使用 sender() 函数判断是哪个对象发射的信号。

connect(button1, SIGNAL(clicked()), this, SLOT(handleButton()));
connect(button2, SIGNAL(clicked()), this, SLOT(handleButton()));// 在槽函数中:
void MyClass::handleButton()
{QPushButton *clickedButton = qobject_cast<QPushButton*>(sender());if (clickedButton) {// 根据clickedButton判断是哪个按钮被点击了}
}
​断开连接​

使用 disconnect 函数断开信号槽连接,参数形式与 connect 类似。

disconnect(btn, SIGNAL(clicked()), this, SLOT(mySlot()));
// 或者断开某个对象的所有连接
disconnect(btn, 0, 0, 0);

http://www.xdnf.cn/news/1436527.html

相关文章:

  • MTK Linux DRM分析(二十九)- MTK mtk_dsi.c(Part.1)
  • Linux 环境配置 muduo 网络库详细步骤
  • Linux 文本处理三大利器:命令小工具和sed
  • 从理念到实践:三层解耦架构与“无系统”论
  • 基于web的高校学籍管理系统的设计与实现-(源码+LW+可部署)
  • CodeBuddy 在进化:我只输入了一个地址,完成了OneCode3.0基础开发环境的配置构建
  • JWT在线解密/JWT在线解码 - 加菲工具
  • kukekey在线搭建k8sV1.30.4版本
  • 从栈中取出K个硬币的最大面值和-分组背包
  • 【学Python自动化】 8. Python 错误和异常学习笔记
  • 2025年工科生职业发展证书选择与分析
  • 【模型学习】LoRA的原理,及deepseek-vl2下LoRA实现
  • 力扣242:有效的字母异位词
  • JetBrains 2025 全家桶 11合1 Windows直装(含 IDEA PyCharm、WebStorm、DataSpell、DataGrip等
  • C++类和对象(中)- 默认成员函数
  • 什么是数据库管理系统(DBMS)?RDBMS和NoSQL又是什么?
  • 第 2 讲:Kafka Topic 与 Partition 基础
  • Qwen3-Embedding-0.6B 模型结构
  • Go结构体详解:核心概念与实战技巧
  • Redis-底层数据结构篇
  • MySQL-表的约束(上)
  • 开发中使用——鸿蒙本地存储之收藏功能
  • LLM 能不能发展为 AGI?
  • 开源模型应用落地-模型上下文协议(MCP)-构建AI智能体的“万能插座”-“mcp-use”高级用法(十三)
  • 3.2-C++基础组件
  • 重新审视信任基石:公网IP证书对网络安全生态的影响
  • 【Go语言入门教程】 Go语言的起源与技术特点:从诞生到现代编程利器(一)
  • Cursor 教我学 Python
  • 英伟达Jetson Orin NX-YOLOv8s目标检测模型耗时分析
  • 深度集成Dify API:企业级RAG知识库管理平台解决方案