Qt 实战指南
FreeGuideOnline
最新
2026-07-16
bash sudo apt update sudo apt install qt6-base-dev qt6-tools-dev qt6-tools-dev-tools qtcreator
### 1.3 验证环境
打开 Qt Creator,创建新项目:
- 选择 `Application (Qt Widgets)` 模板
- 选择编译套件(Kit),点击运行(绿色三角形)
如果出现空白窗口,则环境就绪。
## 第 2 章:第一个 Qt 窗口程序
### 2.1 手动编写一个简单窗口
创建一个纯文本的 C++ 源文件 `main.cpp`,代码:
```cpp
#include <QApplication>
#include <QLabel>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QLabel label("Hello, Qt 6!");
label.setWindowTitle("我的第一个程序");
label.resize(300, 200);
label.show();
return app.exec();
}
使用 qmake 或 Qt Creator 构建项目。运行后会看到一个显示文字的窗口。
2.2 项目结构剖析
一般的 Qt Widgets 项目包含:
.pro文件:工程文件,定义源文件、头文件和模块依赖main.cpp:程序入口- 类通常继承自
QWidget或其子类,用于搭建界面
示例 .pro 文件:
QT += core gui widgets
TARGET = MyApp
SOURCES += main.cpp
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
2.3 信号与槽初探
信号与槽是 Qt 的核心机制。对象可以发出信号,槽是普通函数,响应信号。
下面是一个按钮点击关闭窗口的例子:
#include <QApplication>
#include <QPushButton>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QPushButton button("退出");
QObject::connect(&button, &QPushButton::clicked, &app, &QApplication::quit);
button.show();
return app.exec();
}
clicked是按钮的信号quit是QApplication的槽- 当按钮被点击,应用程序退出
第 3 章:常用控件与布局
3.1 基本控件速览
| 控件 | 类名 | 作用 |
|---|---|---|
| 按钮 | QPushButton |
带文字的普通按钮 |
| 标签 | QLabel |
显示文本或图片 |
| 单行输入 | QLineEdit |
单行文本输入框 |
| 多行输入 | QTextEdit |
富文本/多行文本编辑 |
| 复选框 | QCheckBox |
多选开关 |
| 单选按钮 | QRadioButton |
互斥选择(配合 QButtonGroup) |
| 组合框 | QComboBox |
下拉列表选择 |
| 滑块 | QSlider |
拖拽取值 |
| 进度条 | QProgressBar |
进度显示 |
3.2 布局管理器
不使用绝对坐标,用布局管理器自动调整控件位置和大小。
常用布局:
QHBoxLayout:水平排列QVBoxLayout:垂直排列QGridLayout:表格网格排列QFormLayout:两列标签-字段表单布局
示例:使用垂直布局放置标签和按钮
#include <QApplication>
#include <QWidget>
#include <QLabel>
#include <QPushButton>
#include <QVBoxLayout>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QWidget window;
window.setWindowTitle("布局示例");
QLabel *label = new QLabel("用户名:");
QPushButton *btn = new QPushButton("登录");
QVBoxLayout *layout = new QVBoxLayout;
layout->addWidget(label);
layout->addWidget(btn);
window.setLayout(layout);
window.show();
return app.exec();
}
第 4 章:深入信号与槽
4.1 自定义槽函数
创建自己的窗口类,继承自 QWidget,添加槽函数。
头文件 MyWidget.h:
#ifndef MYWIDGET_H
#define MYWIDGET_H
#include <QWidget>
#include <QPushButton>
class MyWidget : public QWidget
{
Q_OBJECT
public:
MyWidget(QWidget *parent = nullptr);
private slots:
void onButtonClicked();
private:
QPushButton *m_button;
};
#endif
源文件 MyWidget.cpp:
#include "MyWidget.h"
#include <QMessageBox>
MyWidget::MyWidget(QWidget *parent) : QWidget(parent)
{
m_button = new QPushButton("点我", this);
connect(m_button, &QPushButton::clicked, this, &MyWidget::onButtonClicked);
}
void MyWidget::onButtonClicked()
{
QMessageBox::information(this, "提示", "按钮被点击了!");
}
4.2 带参数的信号传递
许多控件信号携带参数,例如 QLineEdit::textChanged(const QString &text)。
QLineEdit *edit = new QLineEdit;
QObject::connect(edit, &QLineEdit::textChanged, [](const QString &text){
qDebug() << "当前输入:" << text;
});
使用 Lambda 表达式作为槽,简洁方便(C++11 起支持)。
4.3 自定义信号
在类中声明 signals: 区域:
signals:
void valueChanged(int newValue);
发射信号:emit valueChanged(100);
第 5 章:实战项目——简易计算器
5.1 需求与界面设计
制作一个能进行加减乘除的桌面计算器,界面包含:
- 一个
QLineEdit显示表达式和结果 - 数字按钮 0-9
- 运算符按钮
+-*/ - 等于按钮
=,清除按钮C
布局采用 QGridLayout,将按钮放在网格中。
5.2 核心逻辑设计
- 需要存储当前输入的第一个操作数、等待的运算符、以及是否正在输入第二个操作数。
- 点击数字按钮:追加数字到当前输入,更新显示。
- 点击运算符:保存第一个操作数和运算符,清空输入框准备下一个数。
- 点击等号:根据保存的运算符计算,显示结果。
5.3 完整代码实现
Calculator.h
#ifndef CALCULATOR_H
#define CALCULATOR_H
#include <QWidget>
#include <QLineEdit>
#include <QPushButton>
class Calculator : public QWidget
{
Q_OBJECT
public:
explicit Calculator(QWidget *parent = nullptr);
private slots:
void digitClicked();
void operatorClicked();
void equalsClicked();
void clear();
private:
void createLayout();
QPushButton* createButton(const QString &text, const char *slot);
QLineEdit *display;
double pending_value = 0;
QString pending_operator;
bool waiting_for_operand = true;
};
#endif
Calculator.cpp
#include "Calculator.h"
#include <QGridLayout>
#include <QVector>
Calculator::Calculator(QWidget *parent) : QWidget(parent)
{
display = new QLineEdit("0");
display->setReadOnly(true);
display->setAlignment(Qt::AlignRight);
display->setMaxLength(15);
createLayout();
}
void Calculator::createLayout()
{
QGridLayout *layout = new QGridLayout;
layout->addWidget(display, 0, 0, 1, 4);
const QVector<QString> buttons = {
"7", "8", "9", "/",
"4", "5", "6", "*",
"1", "2", "3", "-",
"0", ".", "C", "+",
"="
};
int row = 1, col = 0;
for (const QString &text : buttons) {
QPushButton *button = new QPushButton(text);
if (text == "C") {
connect(button, &QPushButton::clicked, this, &Calculator::clear);
} else if (text == "=") {
layout->addWidget(button, row, col, 1, 4); // 等号跨4列
connect(button, &QPushButton::clicked, this, &Calculator::equalsClicked);
break;
} else if (text == "+" || text == "-" || text == "*" || text == "/") {
connect(button, &QPushButton::clicked, this, &Calculator::operatorClicked);
} else {
connect(button, &QPushButton::clicked, this, &Calculator::digitClicked);
}
layout->addWidget(button, row, col);
col++;
if (col > 3) {
col = 0;
row++;
}
}
setLayout(layout);
setWindowTitle("简易计算器");
}
void Calculator::digitClicked()
{
QPushButton *btn = qobject_cast<QPushButton*>(sender());
QString digit = btn->text();
if (waiting_for_operand) {
display->clear();
waiting_for_operand = false;
}
if (display->text() == "0" && digit == "0")
return; // 避免多个零
if (display->text() == "0" && digit != ".")
display->setText(digit);
else
display->setText(display->text() + digit);
}
void Calculator::operatorClicked()
{
QPushButton *btn = qobject_cast<QPushButton*>(sender());
QString op = btn->text();
if (!waiting_for_operand) {
// 如果之前有输入,则先计算一下
if (!pending_operator.isEmpty())
equalsClicked();
pending_value = display->text().toDouble();
pending_operator = op;
waiting_for_operand = true;
} else {
// 连续点击运算符时更新运算符
pending_operator = op;
}
}
void Calculator::equalsClicked()
{
if (waiting_for_operand)
return;
double right = display->text().toDouble();
double result = 0;
if (pending_operator == "+")
result = pending_value + right;
else if (pending_operator == "-")
result = pending_value - right;
else if (pending_operator == "*")
result = pending_value * right;
else if (pending_operator == "/") {
if (right == 0) {
display->setText("错误");
pending_value = 0;
pending_operator.clear();
waiting_for_operand = true;
return;
}
result = pending_value / right;
} else {
return;
}
display->setText(QString::number(result));
pending_value = result;
pending_operator.clear();
waiting_for_operand = true;
}
void Calculator::clear()
{
display->setText("0");
pending_value = 0;
pending_operator.clear();
waiting_for_operand = true;
}
main.cpp
#include <QApplication>
#include "Calculator.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
Calculator calc;
calc.show();
return app.exec();
}