2. Qt基础控件(上):QWidget、QLabel、QPushButton、QLineEdit、QTextEdit,信号与槽机制入门
各位同学,欢迎来到第二章。这一章我们开始真正动手,接触 Qt 里最常用的一批基础控件。说实话,Qt 的控件体系非常庞大,但别怕——你只要把这几个基础控件吃透,后面再学什么 QComboBox、QTableWidget,上手会快得多。
我个人习惯把 Qt 控件分成两类:显示用的和交互用的。今天讲的五个控件,正好覆盖了这两类。我们先从最基础的 QWidget 说起。
2.1 QWidget:一切控件的根
QWidget 是所有用户界面对象的基类。说白了,你在界面上看到的任何一个按钮、标签、输入框,本质上都是一个 QWidget。它定义了窗口最基本的属性:位置、大小、可见性、鼠标事件处理等。
我在项目中遇到过一个问题:新手经常搞不清 QWidget 和 QMainWindow 的区别。简单说,QMainWindow 是 QWidget 的子类,它自带菜单栏、工具栏、状态栏这些“大件”。如果你只是做一个弹窗或者一个自定义面板,直接用 QWidget 就够了。
核心要点:
- QWidget 是“空画布”,你可以在上面放任何子控件
- 每个 QWidget 都可以作为独立窗口(设置 Qt::Window 标志)
- QWidget 可以嵌套:一个 QWidget 里放另一个 QWidget,形成父子关系
来看一个最简单的例子:
// 创建一个 QWidget 作为顶层窗口
QWidget *window = new QWidget();
window->setWindowTitle("我的第一个窗口");
window->resize(400, 300);
window->show();
嗯,这里要注意:show() 必须调用,否则窗口不会显示。我刚开始学 Qt 时经常忘记这步,调试了半天发现窗口没出来——其实就是没调用 show()。
2.2 QLabel:显示文本和图片
QLabel 是 Qt 里最常用的“显示型”控件。它主要用来展示文本、图片、富文本(HTML)。你想想看,一个界面如果没有文字说明,用户根本不知道每个按钮是干嘛的。QLabel 就是干这个的。
| 方法 | 作用 | 示例 |
|---|---|---|
setText() |
设置普通文本 | label->setText("用户名:"); |
setPixmap() |
设置图片 | label->setPixmap(QPixmap("logo.png")); |
setAlignment() |
设置对齐方式 | label->setAlignment(Qt::AlignCenter); |
setWordWrap() |
设置自动换行 | label->setWordWrap(true); |
小技巧:QLabel 支持简单的 HTML 标签。比如 label->setText("<b>粗体</b> <font color='red'>红色文字</font>"); 可以快速实现富文本效果,省去手动设置样式表的麻烦。
2.3 QPushButton:最常用的交互控件
QPushButton 是 Qt 里最基础的按钮控件。用户点击它,程序做出响应。它的用法极其简单,但背后涉及一个非常重要的概念——信号与槽。
先看代码:
QPushButton *btn = new QPushButton("点击我", parentWidget);
// 连接信号与槽
connect(btn, &QPushButton::clicked, this, &MainWindow::onButtonClicked);
这里 clicked 就是信号,onButtonClicked 就是槽函数。当用户点击按钮时,Qt 会自动发射 clicked 信号,然后执行对应的槽函数。
我曾经犯过一个低级错误:在 connect 时把信号和槽的参数类型写错了,结果编译通过但运行时按钮没反应。Qt 的 connect 是类型安全的,参数不匹配会静默失败。所以,如果你发现按钮点了没反应,第一件事就是检查 connect 的参数。
2.4 QLineEdit:单行文本输入
QLineEdit 是单行文本输入框。登录界面的用户名、密码输入框,搜索框,都是它。
常用功能:
setPlaceholderText():设置占位提示文本(灰色提示文字)setEchoMode():设置回显模式,密码框用QLineEdit::PasswordsetMaxLength():限制最大输入字符数text():获取当前输入的文本
避坑指南:我曾经在做一个用户注册模块时,直接用 lineEdit->text() 获取密码,然后存入数据库。后来发现用户输入了空格和特殊字符,导致数据库报错。记住:永远不要信任用户输入。获取文本后一定要做校验和过滤。
2.5 QTextEdit:多行文本编辑器
QTextEdit 是富文本编辑器,支持多行文本、图片、表格、列表等。如果你需要做一个笔记应用、聊天窗口或者代码编辑器,QTextEdit 是首选。
与 QLineEdit 的区别很明显:
| 特性 | QLineEdit | QTextEdit |
|---|---|---|
| 行数 | 单行 | 多行 |
| 富文本 | 不支持 | 支持(HTML) |
| 常用场景 | 输入框、搜索框 | 编辑器、日志显示 |
| 获取内容 | text() |
toPlainText() 或 toHtml() |
我个人习惯用 QTextEdit 来显示程序运行日志。把日志追加到 QTextEdit 里,用户可以看到实时输出,比用控制台友好得多。
2.6 信号与槽机制入门
信号与槽是 Qt 最核心的机制,没有之一。它解决了对象间通信的问题——当一个对象的状态发生变化时,它需要通知其他对象。传统做法是用回调函数,但回调函数是类型不安全的,而且容易造成耦合。Qt 的信号与槽机制,说白了就是一种类型安全的观察者模式。
来看一个完整的例子:
// 定义信号(在类声明中)
signals:
void valueChanged(int newValue);
// 定义槽(在类声明中)
public slots:
void onValueChanged(int newValue) {
qDebug() << "新值:" << newValue;
}
// 连接信号与槽
connect(sender, &SenderClass::valueChanged,
receiver, &ReceiverClass::onValueChanged);
为什么说它类型安全?因为 connect 函数在编译期就会检查信号和槽的参数是否匹配。如果信号发射 int,槽却接收 QString,编译直接报错。这比 C 语言的回调函数安全得多。
信号与槽的三种连接方式:
- 一对一:一个信号连接一个槽
- 一对多:一个信号连接多个槽,信号发射时所有槽依次执行
- 多对一:多个信号连接同一个槽,任意信号发射都会触发该槽
我记得有一次做项目,需要在一个按钮点击时同时更新三个界面的状态。我一开始写了三个独立的 connect,后来发现可以用一个信号连接三个槽,代码简洁多了。嗯,这就是一对多的典型应用。
2.7 知识体系总览
下面这张图把本章的核心知识点串起来了。你可以看到,QWidget 是所有控件的根,QLabel、QPushButton、QLineEdit、QTextEdit 都继承自它。而信号与槽机制,则是连接这些控件的“神经”。
从这张图你可以看到:QWidget 在最顶层,四个子控件各司其职。信号与槽机制在中间层,负责把用户的操作(点击按钮、输入文本)转换成程序可以处理的“事件”。最下面是三种连接方式,灵活组合就能实现复杂的交互逻辑。
2.8 本章小结
这一章我们学了五个基础控件和一个核心机制。说实话,这些内容在 Qt 里属于“吃饭的家伙”,几乎每个项目都会用到。我的建议是:
- QLabel 和 QPushButton 是最简单的,先拿它们练手
- QLineEdit 和 QTextEdit 注意区分使用场景
- 信号与槽是 Qt 的灵魂,一定要理解“发射信号→执行槽函数”这个流程