第六章 基础控件(一):从QLabel到QComboBox

各位同学,今天我们来聊聊Qt里最常用的一批基础控件。说实话,这些控件你几乎在每个项目里都会碰到。我做了这么多年Qt开发,发现很多新手容易在简单控件上栽跟头——不是不会用,而是用得不够好。

咱们一个一个来看。

6.1 QLabel:不只是显示文字

QLabel是Qt里最基础的控件,说白了就是用来显示文本或图片的。但你别小看它,我见过有人把QLabel玩出花来。

核心功能:

  • 显示纯文本、富文本(HTML)
  • 显示图片(QPixmap)
  • 显示动画(QMovie)
  • 支持超链接

先看个最简单的例子:

// 创建一个标签
QLabel *label = new QLabel("Hello, Qt!", this);
label->setGeometry(50, 50, 200, 30);

// 设置对齐方式
label->setAlignment(Qt::AlignCenter);

// 设置字体
QFont font("微软雅黑", 12, QFont::Bold);
label->setFont(font);

嗯,这里要注意一点。QLabel默认是不接受富文本的,如果你想显示HTML格式的内容,得手动开启:

label->setTextFormat(Qt::RichText);
label->setText("<b>粗体</b> <i>斜体</i> <a href='#'>链接</a>");

我个人习惯在显示提示信息时用QLabel加HTML,比如错误提示用红色,成功提示用绿色,这样用户体验会好很多。

小技巧:QLabel的setWordWrap(true)可以开启自动换行,适合显示长文本。

6.2 QPushButton:按钮的进阶用法

QPushButton,Qt里最常用的按钮。你可能觉得按钮有什么好讲的?点一下触发信号不就完了?其实不然。

我在项目中遇到过这样一个需求:按钮需要显示图标和文字,而且图标要动态切换。很多人会用QPushButton配合QIcon来实现:

QPushButton *btn = new QPushButton("保存", this);
btn->setIcon(QIcon(":/icons/save.png"));
btn->setIconSize(QSize(24, 24));

// 连接信号
connect(btn, &QPushButton::clicked, this, [=]() {
    qDebug() << "按钮被点击了";
});

但如果你想让按钮更灵活一点,比如显示多行文字,或者自定义样式,那就得用setStyleSheet了:

btn->setStyleSheet(
    "QPushButton {"
    "  background-color: #4CAF50;"
    "  color: white;"
    "  border-radius: 5px;"
    "  padding: 8px 16px;"
    "}"
    "QPushButton:hover {"
    "  background-color: #45a049;"
    "}"
    "QPushButton:pressed {"
    "  background-color: #3d8b40;"
    "}"
);

避坑指南:我曾经在项目里直接用setStyleSheet覆盖了所有QPushButton的样式,结果发现对话框里的标准按钮(如QDialogButtonBox)也跟着变了。后来我学乖了,要么给按钮设置objectName,要么用类选择器限定范围。

6.3 QLineEdit:单行输入的那些坑

QLineEdit是单行文本输入框。看起来简单,但用起来有不少门道。

先看基本用法:

QLineEdit *edit = new QLineEdit(this);
edit->setPlaceholderText("请输入用户名...");
edit->setMaxLength(20);

// 获取输入内容
QString text = edit->text();

常用的设置:

方法 说明
setEchoMode() 设置显示模式(密码、普通等)
setValidator() 设置输入验证器
setInputMask() 设置输入掩码
setReadOnly() 设置为只读

密码输入框是个典型场景:

QLineEdit *pwdEdit = new QLineEdit(this);
pwdEdit->setEchoMode(QLineEdit::Password);
pwdEdit->setPlaceholderText("请输入密码");

你想想看,如果用户输入密码时能看到明文,那得多尴尬。所以EchoMode一定要设对。

个人经验:我习惯在输入框后面加一个"显示/隐藏密码"的小按钮,用QAction实现。用户体验会好很多。

6.4 QTextEdit vs QPlainTextEdit:选哪个?

这两个控件都是多行文本编辑器,但侧重点不同。很多新手搞不清区别,我简单说一下。

QTextEdit:支持富文本,可以显示图片、表格、HTML。适合做简单的文本编辑器。

QPlainTextEdit:纯文本,性能更好,适合显示日志、代码等大量文本。

看个对比:

// QTextEdit - 支持富文本
QTextEdit *richEdit = new QTextEdit(this);
richEdit->setHtml("<h2>标题</h2><p>这是<b>粗体</b>文字</p>");

// QPlainTextEdit - 纯文本,性能好
QPlainTextEdit *plainEdit = new QPlainTextEdit(this);
plainEdit->setPlainText("这是纯文本\n第二行");

我在项目中用QPlainTextEdit显示过几十万行的日志,滚动依然流畅。换成QTextEdit的话,早就卡死了。所以,如果你只是显示纯文本,别犹豫,用QPlainTextEdit。

核心区别总结:

  • QTextEdit:功能丰富,支持富文本,适合编辑文档
  • QPlainTextEdit:轻量高效,纯文本,适合显示大量数据

6.5 QComboBox:下拉框的灵活运用

QComboBox,下拉选择框。用法很直观:

QComboBox *combo = new QComboBox(this);
combo->addItem("选项一");
combo->addItem("选项二");
combo->addItem("选项三");

// 设置当前选中项
combo->setCurrentIndex(0);

// 获取选中项
QString selected = combo->currentText();
int index = combo->currentIndex();

但QComboBox远不止这么简单。它支持可编辑模式,用户可以直接输入内容:

combo->setEditable(true);
combo->setInsertPolicy(QComboBox::NoInsert); // 不自动插入

还可以给每个选项绑定自定义数据:

combo->addItem("北京", QVariant(1));
combo->addItem("上海", QVariant(2));
combo->addItem("广州", QVariant(3));

// 获取数据
int cityId = combo->currentData().toInt();

嗯,这里要注意。如果你用setEditable(true),用户输入的内容可能不在下拉列表里。我曾经在项目里没处理好这个,结果用户乱输入导致程序崩溃。后来我加了个验证逻辑:

connect(combo, &QComboBox::currentTextChanged, this, [=](const QString &text) {
    if (combo->findText(text) == -1) {
        // 用户输入了非法内容
        combo->setCurrentIndex(0);
    }
});

避坑指南:QComboBox的currentIndexChanged信号在编程设置时也会触发。如果你在初始化时用setCurrentIndex,记得先断开信号连接,或者用blockSignals。

知识体系总览

为了让你更直观地理解这些控件的关系,我画了一张图:

Qt基础控件知识体系 基础控件 QLabel QPushButton QLineEdit QTextEdit QComboBox 文本 / 图片 / 动画 富文本 / 超链接 图标 + 文字 样式表定制 输入掩码 / 验证器 密码模式 / 占位符 富文本编辑 图片 / 表格 可编辑模式 自定义数据绑定 每个控件都有其适用场景,选对控件事半功倍

这张图把五个控件的核心特性都列出来了。你可以看到,每个控件都有自己的专长领域。比如QLabel擅长展示,QPushButton擅长交互,QLineEdit擅长单行输入,QTextEdit和QPlainTextEdit擅长多行文本,QComboBox擅长选择。

好了,这一章的内容就到这里。这些控件虽然基础,但用好它们能解决80%的界面需求。下一章我们会继续深入其他基础控件,敬请期待。


公众号:蓝海资料掘金营,微信deep3321