跳到主要内容

基础控件

Qt Widgets 提供了丰富的桌面控件,本节介绍最常用的基础控件及其用法。

控件基础

Qt 的所有控件都继承自 QWidget,具有共同的特性:

// 所有控件共有的属性和方法
widget->setEnabled(false); // 禁用/启用
widget->setVisible(true); // 显示/隐藏
widget->setWindowTitle("Title"); // 窗口标题
widget->resize(400, 300); // 设置大小
widget->move(100, 100); // 设置位置
widget->setStyleSheet("color: red"); // 样式表

QLabel(标签)

用于显示文本或图片,是最简单的控件。

#include <QLabel>

// 文本标签
QLabel *textLabel = new QLabel("Hello Qt", this);
textLabel->setText("新文本");
textLabel->setAlignment(Qt::AlignCenter); // 居中对齐

// HTML 富文本
QLabel *htmlLabel = new QLabel(this);
htmlLabel->setText("<h1>标题</h1><p style='color:red'>红色文字</p>");

// 图片标签
QLabel *imageLabel = new QLabel(this);
imageLabel->setPixmap(QPixmap(":/images/logo.png"));
imageLabel->setScaledContents(true); // 图片自适应大小

// 动态更新文本
int count = 0;
label->setText(QString("点击次数: %1").arg(++count));

常用属性

方法说明
setText()设置文本内容
setPixmap()设置图片
setAlignment()对齐方式(左/右/居中)
setWordWrap()自动换行
setTextInteractionFlags()文本交互(可选中/可链接)

QPushButton(按钮)

最常用的交互控件,响应点击事件。

#include <QPushButton>

// 创建按钮
QPushButton *button = new QPushButton("点击我", this);

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

// 设置图标
button->setIcon(QIcon(":/icons/save.png"));
button->setIconSize(QSize(32, 32));

// 设置快捷键
button->setShortcut(QKeySequence("Ctrl+S"));

// 设置样式
button->setStyleSheet(R"(
QPushButton {
background-color: #4CAF50;
color: white;
border: none;
padding: 10px 20px;
border-radius: 4px;
}
QPushButton:hover {
background-color: #45a049;
}
QPushButton:pressed {
background-color: #3d8b40;
}
QPushButton:disabled {
background-color: #cccccc;
}
)");

// 切换按钮(可勾选)
QPushButton *toggleBtn = new QPushButton("开关", this);
toggleBtn->setCheckable(true);
connect(toggleBtn, &QPushButton::toggled, this, [=](bool checked) {
qDebug() << "状态:" << (checked ? "开启" : "关闭");
});

QLineEdit(单行输入框)

用于接收用户单行文本输入。

#include <QLineEdit>

// 创建输入框
QLineEdit *lineEdit = new QLineEdit(this);
lineEdit->setPlaceholderText("请输入用户名"); // 提示文本

// 获取和设置文本
lineEdit->setText("默认值");
QString text = lineEdit->text();

// 信号连接
connect(lineEdit, &QLineEdit::textChanged, this, [=](const QString &text) {
qDebug() << "文本变化:" << text;
});

connect(lineEdit, &QLineEdit::returnPressed, this, [=]() {
qDebug() << "按下回车:" << lineEdit->text();
});

// 密码输入
QLineEdit *pwdEdit = new QLineEdit(this);
pwdEdit->setEchoMode(QLineEdit::Password); // 显示为密码
// 其他模式:Normal, NoEcho, PasswordEchoOnEdit

// 输入限制
lineEdit->setMaxLength(20); // 最大长度
lineEdit->setValidator(new QIntValidator(0, 100, this)); // 只能输入0-100的整数
lineEdit->setInputMask("0000-00-00"); // 日期格式掩码

// 自动补全
QStringList words;
words << "apple" << "application" << "banana" << "cherry";
QCompleter *completer = new QCompleter(words, this);
completer->setCaseSensitivity(Qt::CaseInsensitive);
lineEdit->setCompleter(completer);

输入验证器

// 整数验证
lineEdit->setValidator(new QIntValidator(0, 9999, this));

// 浮点数验证
lineEdit->setValidator(new QDoubleValidator(0.0, 100.0, 2, this));

// 正则表达式验证(邮箱)
QRegularExpression rx("\\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,}\\b");
lineEdit->setValidator(new QRegularExpressionValidator(rx, this));

QTextEdit(多行文本编辑)

支持多行文本、富文本编辑。

#include <QTextEdit>

// 创建文本编辑器
QTextEdit *textEdit = new QTextEdit(this);
textEdit->setPlaceholderText("请输入内容...");

// 设置和获取文本
textEdit->setPlainText("普通文本");
textEdit->setHtml("<b>粗体</b> 和 <i>斜体</i>");
QString text = textEdit->toPlainText();
QString html = textEdit->toHtml();

// 追加文本
textEdit->append("新行文本");

// 只读模式
textEdit->setReadOnly(true);

// 信号
connect(textEdit, &QTextEdit::textChanged, this, [=]() {
qDebug() << "内容变化";
});

// 设置字体
textEdit->setFont(QFont("Microsoft YaHei", 12));

// 限制输入
textEdit->setMaximumBlockCount(100); // 最多100行

QComboBox(下拉框)

提供下拉选择列表。

#include <QComboBox>

// 创建下拉框
QComboBox *comboBox = new QComboBox(this);

// 添加选项
comboBox->addItem("选项1");
comboBox->addItem("选项2");
comboBox->addItems({"选项3", "选项4", "选项5"});

// 带图标的选项
comboBox->addItem(QIcon(":/icons/user.png"), "用户");

// 设置当前选中项
comboBox->setCurrentIndex(0);
comboBox->setCurrentText("选项2");

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

// 信号
connect(comboBox, QOverload<int>::of(&QComboBox::currentIndexChanged),
this, [=](int index) {
qDebug() << "选中索引:" << index;
});

// 可编辑下拉框
comboBox->setEditable(true);
comboBox->setInsertPolicy(QComboBox::InsertAtBottom);

// 用户数据
comboBox->addItem("北京", 110000); // 显示文本,存储城市代码
int cityCode = comboBox->currentData().toInt();

QCheckBox & QRadioButton(复选框和单选框)

#include <QCheckBox>
#include <QRadioButton>
#include <QButtonGroup>

// 复选框
QCheckBox *checkBox = new QCheckBox("同意协议", this);
checkBox->setChecked(true);

connect(checkBox, &QCheckBox::stateChanged, this, [=](int state) {
if (state == Qt::Checked) {
qDebug() << "已勾选";
} else if (state == Qt::Unchecked) {
qDebug() << "未勾选";
} else if (state == Qt::PartiallyChecked) {
qDebug() << "部分勾选";
}
});

// 三态复选框
checkBox->setTristate(true);

// 单选按钮(需要分组)
QButtonGroup *group = new QButtonGroup(this);

QRadioButton *radio1 = new QRadioButton("男", this);
QRadioButton *radio2 = new QRadioButton("女", this);
QRadioButton *radio3 = new QRadioButton("保密", this);

group->addButton(radio1, 1);
group->addButton(radio2, 2);
group->addButton(radio3, 3);

radio1->setChecked(true); // 默认选中

connect(group, QOverload<int>::of(&QButtonGroup::buttonClicked),
this, [=](int id) {
qDebug() << "选中:" << id;
});

QSlider & QSpinBox(滑块和数字框)

#include <QSlider>
#include <QSpinBox>

// 滑块
QSlider *slider = new QSlider(Qt::Horizontal, this);
slider->setRange(0, 100);
slider->setValue(50);
slider->setTickPosition(QSlider::TicksBelow);
slider->setTickInterval(10);

// 数字框
QSpinBox *spinBox = new QSpinBox(this);
spinBox->setRange(0, 100);
spinBox->setValue(50);
spinBox->setSuffix("%"); // 后缀

// 双向绑定
connect(slider, &QSlider::valueChanged, spinBox, &QSpinBox::setValue);
connect(spinBox, QOverload<int>::of(&QSpinBox::valueChanged),
slider, &QSlider::setValue);

// 浮点数版本
QDoubleSpinBox *doubleSpin = new QDoubleSpinBox(this);
doubleSpin->setRange(0.0, 1.0);
doubleSpin->setSingleStep(0.1);
doubleSpin->setDecimals(2);

QProgressBar(进度条)

#include <QProgressBar>

QProgressBar *progressBar = new QProgressBar(this);
progressBar->setRange(0, 100);
progressBar->setValue(50);

// 样式
progressBar->setTextVisible(true);
progressBar->setFormat("%p% (%v/%m)"); // 显示百分比和数值

// 不确定模式(加载中)
progressBar->setRange(0, 0); // 最大值设为0进入不确定模式

// 更新进度
for (int i = 0; i <= 100; i++) {
progressBar->setValue(i);
QThread::msleep(50); // 模拟工作
QCoreApplication::processEvents(); // 处理界面事件
}

布局管理

控件需要通过布局管理器来组织位置。

常用布局

#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QGridLayout>
#include <QFormLayout>

// 垂直布局
QVBoxLayout *vLayout = new QVBoxLayout(this);
vLayout->addWidget(label);
vLayout->addWidget(lineEdit);
vLayout->addWidget(button);
vLayout->addStretch(); // 弹性空间,将控件推到顶部

// 水平布局
QHBoxLayout *hLayout = new QHBoxLayout();
hLayout->addWidget(okButton);
hLayout->addWidget(cancelButton);
hLayout->addStretch();

// 嵌套布局
vLayout->addLayout(hLayout);

// 网格布局
QGridLayout *grid = new QGridLayout();
grid->addWidget(new QLabel("姓名:"), 0, 0);
grid->addWidget(nameEdit, 0, 1);
grid->addWidget(new QLabel("年龄:"), 1, 0);
grid->addWidget(ageSpin, 1, 1);
grid->addWidget(new QLabel("地址:"), 2, 0);
grid->addWidget(addressEdit, 2, 1, 1, 2); // 跨2列

// 表单布局(标签-字段成对)
QFormLayout *form = new QFormLayout();
form->addRow("用户名:", usernameEdit);
form->addRow("密码:", passwordEdit);
form->addRow("邮箱:", emailEdit);

布局属性

// 边距和间距
layout->setContentsMargins(10, 10, 10, 10); // 左、上、右、下
layout->setSpacing(10); // 控件间距

// 拉伸因子
hLayout->addWidget(widget1, 1); // 拉伸因子1
hLayout->addWidget(widget2, 2); // 拉伸因子2(占更多空间)

// 对齐方式
layout->addWidget(widget, 0, Qt::AlignCenter); // 居中对齐

完整示例:登录表单

class LoginDialog : public QDialog
{
Q_OBJECT

public:
LoginDialog(QWidget *parent = nullptr) : QDialog(parent)
{
setWindowTitle("用户登录");
setFixedSize(400, 200);

// 创建控件
QLabel *userLabel = new QLabel("用户名:", this);
QLabel *pwdLabel = new QLabel("密码:", this);

QLineEdit *userEdit = new QLineEdit(this);
userEdit->setPlaceholderText("请输入用户名");

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

QCheckBox *rememberCheck = new QCheckBox("记住密码", this);

QPushButton *loginBtn = new QPushButton("登录", this);
QPushButton *cancelBtn = new QPushButton("取消", this);

// 布局
QGridLayout *grid = new QGridLayout();
grid->addWidget(userLabel, 0, 0);
grid->addWidget(userEdit, 0, 1);
grid->addWidget(pwdLabel, 1, 0);
grid->addWidget(pwdEdit, 1, 1);
grid->addWidget(rememberCheck, 2, 1);

QHBoxLayout *btnLayout = new QHBoxLayout();
btnLayout->addStretch();
btnLayout->addWidget(loginBtn);
btnLayout->addWidget(cancelBtn);

QVBoxLayout *mainLayout = new QVBoxLayout(this);
mainLayout->addLayout(grid);
mainLayout->addLayout(btnLayout);

// 信号连接
connect(loginBtn, &QPushButton::clicked, this, [=]() {
QString username = userEdit->text();
QString password = pwdEdit->text();

if (username.isEmpty() || password.isEmpty()) {
QMessageBox::warning(this, "警告", "用户名和密码不能为空");
return;
}

// 执行登录...
accept(); // 关闭对话框,返回 Accepted
});

connect(cancelBtn, &QPushButton::clicked, this, &QDialog::reject);
}
};

下一步

掌握了基础控件后,继续学习 容器控件 了解分组框、标签页等组织控件的容器。