15、Qt Widgets基础(上):QWidget、QLabel、QPushButton、QLineEdit、布局管理器
好,咱们今天正式进入 Qt Widgets 的世界。说实话,这部分内容是我个人觉得 Qt 最亲切的地方——你拖拖拽拽、写几行代码,一个窗口就出来了。很多初学者一上来就问我:「老师,Qt 到底难不难?」我的回答是:如果你理解了今天这几个基础控件和布局,Qt 的大门就算被你踹开了。
咱们今天要聊的,是 Qt 里最常用、最核心的几个 Widget:QWidget、QLabel、QPushButton、QLineEdit,以及两个布局管理器 QHBoxLayout 和 QVBoxLayout。这些东西,说白了就是你写任何桌面应用都绕不开的「砖块」。
QWidget:一切控件的祖宗
QWidget 是 Qt 里所有用户界面对象的基类。你看到的按钮、标签、输入框,甚至整个窗口,本质上都是 QWidget 的子类。它提供了最基础的功能:绘制自己、处理鼠标键盘事件、管理子控件。
我个人习惯把 QWidget 想象成一张「白纸」。你可以在上面画东西,也可以在上面放其他控件。比如你创建一个空窗口,其实就是一个 QWidget 对象。
#include <QApplication>
#include <QWidget>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QWidget window;
window.setWindowTitle("我的第一个窗口");
window.resize(400, 300);
window.show();
return app.exec();
}
这段代码跑起来,你会看到一个 400x300 的空白窗口。嗯,这里要注意:show() 必须调用,否则窗口不会显示。我在项目里见过新手调了半天,结果发现忘了写 show()——这种事我也干过。
QLabel:显示文本和图片
QLabel 是 Qt 里最常用的文本显示控件。你用它来显示提示信息、标题、或者简单的富文本内容。它支持 HTML 子集,所以你可以加粗、变色、甚至插入图片。
#include <QLabel>
QLabel *label = new QLabel("Hello, Qt!", &window);
label->setText("<b>欢迎</b>来到 <font color='red'>C++与Qt</font> 的世界");
label->setAlignment(Qt::AlignCenter);
label->setGeometry(50, 50, 300, 40);
你看,setText() 里可以直接写 HTML 标签。不过要注意,QLabel 默认是不接受用户输入的——它只是个「展示者」。如果你想让它显示图片,用 setPixmap() 就行。
我曾经在做一个配置工具时,用 QLabel 显示设备状态图标。绿色表示在线,红色表示离线。配合 setPixmap() 切换图片,效果非常直观。
QPushButton:点击触发动作
按钮,不用我多说了吧?用户点击它,程序执行某个操作。QPushButton 是 Qt 里最标准的按钮控件。
#include <QPushButton>
QPushButton *btn = new QPushButton("点击我", &window);
btn->setGeometry(150, 150, 100, 40);
// 连接点击信号
QObject::connect(btn, &QPushButton::clicked, [&]() {
label->setText("按钮被点击了!");
});
这里用到了 Qt 的信号与槽机制。clicked 是按钮点击时发出的信号,后面的 lambda 表达式就是槽函数。说白了,就是「按钮被点了,执行这段代码」。
clicked() 和 pressed() 搞混了。clicked 是鼠标松开时才触发,pressed 是按下去就触发。如果你要做「长按」效果,记得用 pressed 和 released 组合。
QLineEdit:单行文本输入
用户输入信息,靠的就是 QLineEdit。它支持单行文本的输入、编辑、复制粘贴等操作。你还可以设置占位提示文本、输入掩码、密码模式等。
#include <QLineEdit>
QLineEdit *edit = new QLineEdit(&window);
edit->setPlaceholderText("请输入用户名...");
edit->setGeometry(50, 100, 300, 30);
// 获取输入内容
QString text = edit->text();
// 连接文本变化信号
QObject::connect(edit, &QLineEdit::textChanged, [&](const QString &text) {
label->setText("你输入了: " + text);
});
你想想看,textChanged 信号会在用户每次输入时触发。这在做实时搜索、输入校验时非常有用。比如我做过一个登录界面,用户输入密码时,我监听 textChanged 来实时检查密码强度。
另外,setEchoMode(QLineEdit::Password) 可以把输入内容显示为圆点,适合密码输入框。
布局管理器:让控件自动排列
如果你手动用 setGeometry() 摆放控件,窗口一拉伸,控件位置就乱了。布局管理器就是来解决这个问题的。它会根据窗口大小自动调整子控件的位置和大小。
QHBoxLayout:水平布局
水平布局把控件从左到右排成一行。
#include <QHBoxLayout>
QHBoxLayout *hLayout = new QHBoxLayout();
hLayout->addWidget(new QPushButton("左"));
hLayout->addWidget(new QPushButton("中"));
hLayout->addWidget(new QPushButton("右"));
// 把布局设置到窗口上
window.setLayout(hLayout);
三个按钮会水平排列,窗口拉伸时它们会跟着调整宽度。你还可以用 addStretch() 添加弹性空间,让按钮靠左或靠右。
QVBoxLayout:垂直布局
垂直布局把控件从上到下排成一列。
#include <QVBoxLayout>
QVBoxLayout *vLayout = new QVBoxLayout();
vLayout->addWidget(new QLabel("用户名:"));
vLayout->addWidget(new QLineEdit());
vLayout->addWidget(new QPushButton("登录"));
window.setLayout(vLayout);
这样标签、输入框、按钮就垂直排列了。实际项目中,我经常把水平布局和垂直布局嵌套使用,比如外面用垂直布局,里面某一行用水平布局。
QVBoxLayout 里放多个 QHBoxLayout,实现复杂的界面布局。而且布局管理器会自动处理控件的间距和边距,你只需要调用 setSpacing() 和 setContentsMargins() 微调即可。
综合示例:一个简单的登录界面
咱们把今天学的知识串起来,写一个简单的登录界面。
#include <QApplication>
#include <QWidget>
#include <QLabel>
#include <QLineEdit>
#include <QPushButton>
#include <QVBoxLayout>
#include <QHBoxLayout>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QWidget window;
window.setWindowTitle("登录");
window.resize(300, 200);
// 创建控件
QLabel *userLabel = new QLabel("用户名:");
QLineEdit *userEdit = new QLineEdit();
userEdit->setPlaceholderText("请输入用户名");
QLabel *pwdLabel = new QLabel("密码:");
QLineEdit *pwdEdit = new QLineEdit();
pwdEdit->setPlaceholderText("请输入密码");
pwdEdit->setEchoMode(QLineEdit::Password);
QPushButton *loginBtn = new QPushButton("登录");
QPushButton *cancelBtn = new QPushButton("取消");
// 创建布局
QVBoxLayout *mainLayout = new QVBoxLayout();
QHBoxLayout *userLayout = new QHBoxLayout();
userLayout->addWidget(userLabel);
userLayout->addWidget(userEdit);
QHBoxLayout *pwdLayout = new QHBoxLayout();
pwdLayout->addWidget(pwdLabel);
pwdLayout->addWidget(pwdEdit);
QHBoxLayout *btnLayout = new QHBoxLayout();
btnLayout->addStretch();
btnLayout->addWidget(loginBtn);
btnLayout->addWidget(cancelBtn);
mainLayout->addLayout(userLayout);
mainLayout->addLayout(pwdLayout);
mainLayout->addLayout(btnLayout);
window.setLayout(mainLayout);
window.show();
return app.exec();
}
这个例子把标签和输入框用水平布局放在一行,按钮用水平布局靠右排列,外面再用垂直布局把三行串起来。窗口拉伸时,所有控件都会自适应——这就是布局管理器的威力。
好了,今天的内容就到这里。你掌握了 QWidget、QLabel、QPushButton、QLineEdit 这四个基础控件,以及 QHBoxLayout 和 QVBoxLayout 两个布局管理器。这些是 Qt 桌面开发的基石,多写几个小例子,很快就能上手。
setGeometry() 的方式感受控件的位置,然后再切换到布局管理器。这样你能更深刻地理解「布局管理器到底帮我们省了什么事」。