4、Qt常用控件(上):QWidget、QLabel、QPushButton、QLineEdit、QTextEdit

控件,说白了就是界面上的积木块。你想想看,一个完整的嵌入式设备界面,无非就是按钮、标签、输入框这些东西拼起来的。Qt把这些基础积木封装成了一个个类,咱们今天先啃五个最常用的。

我个人习惯把控件分成两类:容器型和功能型。QWidget属于前者,剩下四个属于后者。先搞清楚这个分类,后面学起来会顺很多。

核心观点:Qt控件体系以QWidget为根,所有可视元素都继承自它。掌握这五个控件,就能覆盖80%以上的基础界面需求。

Qt常用控件继承关系(本章范围) QObject QWidget(本章核心) QLabel QPushButton QLineEdit QTextEdit 说明 • QWidget 是所有可视控件的基类,本身也是一个空白容器 • QLabel 显示静态文本/图片;QPushButton 触发动作 • QLineEdit 单行输入;QTextEdit 多行富文本编辑

4.1 QWidget:一切控件的根

QWidget是Qt里最基础的类。你看到的每个窗口、每个按钮、每个输入框,本质上都是一个QWidget。它定义了控件的基本行为:位置、大小、可见性、父子关系。

我在项目里经常把QWidget当作容器面板来用。比如一个设备参数设置界面,我会先new一个QWidget作为主面板,然后在上面放各种子控件。这样做的好处是——想整体隐藏或移动这组控件时,只需要操作父容器就行。

实用技巧:QWidget的setStyleSheet()方法支持QSS(类似CSS)语法。我习惯在构造函数里统一写样式,而不是在UI文件里配。这样代码可维护性高很多。

// 创建一个带边框和背景色的容器面板
QWidget *panel = new QWidget(this);
panel->setGeometry(20, 20, 300, 200);
panel->setStyleSheet(
    "background-color: #f5f5f5;"
    "border: 2px solid #cccccc;"
    "border-radius: 8px;"
);

嗯,这里要注意:QWidget默认不显示背景色。你直接setStyleSheet设背景色可能没效果,需要先调setAutoFillBackground(true)。我刚开始做Qt时就被这个坑过,折腾了半小时才发现。

4.2 QLabel:不只是显示文字

QLabel最基础的用法就是显示一行文本。但它的能力远不止于此——可以显示图片、动图、富文本,甚至可以作为链接跳转的载体。

我曾经在一个工业仪表盘项目里,用QLabel显示实时传感器数值。每秒更新一次,配合QSS把字体调成数码管风格,效果非常棒。

方法 作用 常用场景
setText() 设置纯文本 显示标签、状态信息
setPixmap() 设置图片 显示图标、设备状态图
setMovie() 设置动图 加载等待动画
setOpenExternalLinks() 允许链接跳转 帮助文档、版本信息
// 显示富文本标签,支持HTML
QLabel *infoLabel = new QLabel(this);
infoLabel->setText(
    "<h2 style='color:#2c3e50;'>设备状态</h2>"
    "<p>当前温度:<b style='color:#e74c3c;'>45°C</b></p>"
    "<a href='http://example.com'>查看详情</a>"
);
infoLabel->setOpenExternalLinks(true);  // 允许点击链接

避坑指南:我曾经在嵌入式板子上用QLabel显示大图片,结果界面卡死了。原因是没有缩放图片。记住:setPixmap()之前先调pixmap.scaled(),控制图片尺寸。

4.3 QPushButton:最常用的交互入口

按钮嘛,点一下触发一个动作。QPushButton支持文本、图标、快捷键、菜单弹出等特性。在嵌入式设备上,按钮通常比较大,方便触摸操作。

我个人习惯把按钮的点击响应写成Lambda表达式,这样代码逻辑集中,不用到处找槽函数定义。

QPushButton *btnStart = new QPushButton("启动设备", this);
btnStart->setGeometry(100, 100, 160, 50);
btnStart->setStyleSheet(
    "QPushButton {"
    "   background-color: #27ae60;"
    "   color: white;"
    "   font-size: 16px;"
    "   border-radius: 8px;"
    "}"
    "QPushButton:hover {"
    "   background-color: #2ecc71;"
    "}"
    "QPushButton:pressed {"
    "   background-color: #1e8449;"
    "}"
);

// Lambda连接信号槽,简洁明了
connect(btnStart, &QPushButton::clicked, [=]() {
    qDebug() << "设备启动中...";
    // 这里写启动逻辑
});

你想想看,如果每个按钮都写一个独立的槽函数,文件会变得很臃肿。Lambda方式把逻辑和UI绑定在一起,阅读代码时一目了然。

4.4 QLineEdit:单行文本输入

QLineEdit用于输入用户名、密码、IP地址、数值等单行内容。它支持输入掩码、验证器、回显模式(密码模式)等特性。

我记得在一个网络配置界面里,需要用户输入IP地址。如果不用输入掩码,用户可能乱填格式。用setInputMask()可以强制格式,省去很多校验工作。

功能 方法 示例
输入掩码 setInputMask() "000.000.000.000" 限制IP格式
密码模式 setEchoMode() QLineEdit::Password
占位提示 setPlaceholderText() "请输入用户名"
最大长度 setMaxLength() 限制输入字符数
// 密码输入框
QLineEdit *pwdEdit = new QLineEdit(this);
pwdEdit->setPlaceholderText("请输入密码");
pwdEdit->setEchoMode(QLineEdit::Password);
pwdEdit->setMaxLength(16);

// IP地址输入,带掩码
QLineEdit *ipEdit = new QLineEdit(this);
ipEdit->setInputMask("000.000.000.000");
ipEdit->setText("192.168.001.100");

经验之谈:嵌入式设备上软键盘弹出时,QLineEdit可能会被遮挡。我一般会在布局里给输入框留足底部空间,或者用scrollArea包裹整个表单。

4.5 QTextEdit:多行富文本编辑器

QTextEdit比QLineEdit强大得多。它支持多行文本、富文本(HTML)、图片嵌入、撤销/重做、打印等功能。在嵌入式设备上,常用于日志显示、协议调试、配置编辑等场景。

我曾经做一个设备调试工具,用QTextEdit显示串口日志。每秒几百条数据往里追加,如果直接用append(),界面会越来越卡。后来我加了限制:超过1000行就自动清除前半部分。

// 日志显示控件
QTextEdit *logView = new QTextEdit(this);
logView->setReadOnly(true);  // 只读模式,用户不能编辑
logView->setStyleSheet("background-color: #1e1e1e; color: #00ff00; font-family: monospace;");

// 追加日志,带时间戳
void appendLog(const QString &msg) {
    QString timestamp = QDateTime::currentDateTime().toString("hh:mm:ss.zzz");
    logView->append("[" + timestamp + "] " + msg);

    // 限制最大行数,防止内存溢出
    if (logView->document()->blockCount() > 1000) {
        QTextCursor cursor = logView->textCursor();
        cursor.movePosition(QTextCursor::Start);
        cursor.select(QTextCursor::BlockUnderCursor);
        cursor.removeSelectedText();
        cursor.deleteChar();  // 删除换行符
    }
}

实用技巧:QTextEdit的document()返回QTextDocument对象,可以精细控制文本格式。比如高亮某一行、插入表格、设置字体颜色等。这在协议解析界面里非常有用。

4.6 综合示例:设备登录界面

把上面五个控件组合起来,做一个简单的设备登录界面。这个例子在真实项目中经常作为启动页使用。

// 主容器
QWidget *loginPanel = new QWidget(this);
loginPanel->setGeometry(50, 50, 400, 300);
loginPanel->setStyleSheet("background-color: #ffffff; border-radius: 10px;");

// 标题标签
QLabel *titleLabel = new QLabel("设备登录", loginPanel);
titleLabel->setGeometry(150, 20, 100, 30);
titleLabel->setStyleSheet("font-size: 20px; font-weight: bold; color: #2c3e50;");

// 用户名输入
QLabel *userLabel = new QLabel("用户名:", loginPanel);
userLabel->setGeometry(50, 80, 60, 30);
QLineEdit *userEdit = new QLineEdit(loginPanel);
userEdit->setGeometry(120, 80, 220, 30);
userEdit->setPlaceholderText("请输入用户名");

// 密码输入
QLabel *pwdLabel = new QLabel("密  码:", loginPanel);
pwdLabel->setGeometry(50, 130, 60, 30);
QLineEdit *pwdEdit = new QLineEdit(loginPanel);
pwdEdit->setGeometry(120, 130, 220, 30);
pwdEdit->setEchoMode(QLineEdit::Password);
pwdEdit->setPlaceholderText("请输入密码");

// 登录按钮
QPushButton *loginBtn = new QPushButton("登 录", loginPanel);
loginBtn->setGeometry(150, 190, 100, 40);
loginBtn->setStyleSheet(
    "QPushButton { background-color: #3498db; color: white; font-size: 16px; border-radius: 6px; }"
    "QPushButton:hover { background-color: #2980b9; }"
);

// 状态信息
QLabel *statusLabel = new QLabel("", loginPanel);
statusLabel->setGeometry(50, 250, 300, 30);
statusLabel->setStyleSheet("color: #e74c3c; font-size: 14px;");

// 登录逻辑
connect(loginBtn, &QPushButton::clicked, [=]() {
    QString user = userEdit->text().trimmed();
    QString pwd = pwdEdit->text();
    if (user.isEmpty() || pwd.isEmpty()) {
        statusLabel->setText("用户名或密码不能为空!");
        return;
    }
    // 实际项目中这里会调后端验证接口
    statusLabel->setText("登录成功,正在跳转...");
    statusLabel->setStyleSheet("color: #27ae60; font-size: 14px;");
});

这个例子虽然简单,但涵盖了本章五个控件的核心用法。你想想看,实际项目中的复杂界面,无非就是这种基础组合的扩展。把每个控件的特性吃透,后面做复杂界面时就能信手拈来。

避坑指南:嵌入式设备屏幕尺寸有限,布局时不要写死坐标。我建议用布局管理器(QHBoxLayout/QVBoxLayout)替代setGeometry。这样在不同分辨率下自动适配,省去很多适配工作。