C++/Qt 方向实训 · 第 2 / 5 天 · 讲:练 ≈ 1:2.7
tools/install_qt_host.sh
cmake -S . -B build -G Ninja -DBUILD_QT_PART=ON \
-DCMAKE_PREFIX_PATH=$PWD/.qt514/5.14.2/gcc_64 -DCMAKE_BUILD_TYPE=Debug
cmake --build build
模块 A · 讲授 35min
class Widget : public QWidget {
Q_OBJECT // 用到信号槽/属性系统的类都要有这个宏(触发 moc 代码生成)
public:
Widget(QWidget* parent = nullptr) : QWidget(parent) {}
};
int main(int argc, char* argv[]) {
QApplication app(argc, argv); // 整个程序唯一的 QApplication
Widget w;
w.show();
return app.exec(); // 进入事件循环,程序在这里“活着”
}
出处:p03/ch02/minimal_qt_app.cpp(注意仓库版本额外注入了
QTimer::singleShot 200ms 自动退出,便于离屏自动化验证,真实项目不需要这一行)
// 第一种:先构造再设属性
QPushButton* btn = new QPushButton;
btn->setParent(this);
btn->setText(QStringLiteral("德玛西亚"));
btn->move(100, 100);
// 第二种:构造时指定文本与父亲
QPushButton* btn2 = new QPushButton(QStringLiteral("孙悟空"), this);
class Teacher : public QObject {
Q_OBJECT
signals:
void hungry(); // 无参信号
void hungry(QString food); // 带参信号(重载)
public slots:
void classIsOver(){ emit hungry(); emit hungry(QString("汉堡")); }
};
// 连接重载信号时必须用 QOverload 显式指定版本
connect(t, QOverload<>::of(&Teacher::hungry), s, QOverload<>::of(&Student::treat));
connect(t, QOverload<QString>::of(&Teacher::hungry), s, QOverload<QString>::of(&Student::treat));
出处:p03/ch04/custom_signal_slot.cpp; lambda 槽 + 值捕获/引用捕获对比见 lambda_signal_slot.cpp
模块 A · 练习 95min
minimal_qt_app 与 button_creationQT_QPA_PLATFORM=offscreen tools/run_qt.sh minimal_qt_app 与
button_creation 均退出码为 0,无崩溃QLabel 的文本内容QLabel 文本确实改变;
用 connect 语法而非直接函数调用builtin_signal_slot.cpp,给一个类定义两个同名不同参的信号,用
QOverload 消歧义连接模块 B · 讲授 35min
QPixmap pixmap;
pixmap.load(":/Image/boat.jpg"); // 从 Qt 资源系统(.qrc)加载
QLabel* label = new QLabel(this);
label->setPixmap(pixmap);
出处:p03/ch08/label_pixmap.cpp; HTML 富文本标签见 label_text_html.cpp
QSpinBox* spin = new QSpinBox(this);
QSlider* slider = new QSlider(Qt::Horizontal, this);
QHBoxLayout* layout = new QHBoxLayout(this);
layout->addWidget(spin);
layout->addWidget(slider);
// spin 变化 → slider 跟随,slider 变化 → spin 跟随
connect(spin, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), slider, &QSlider::setValue);
connect(slider, &QSlider::valueChanged, spin, &QSpinBox::setValue);
出处:p03/ch08/custom_widget.cpp——布局管理器负责排布, 不用手算控件坐标。
okBtn->setObjectName("okButton");
setStyleSheet(
"QPushButton#okButton { background-color: #2f855a; border-radius: 6px; color: white; }"
"QPushButton#okButton:hover { background-color: #276749; }"
);
出处:docs/teaching/examples/qss_styling/qt_qss_styling.cpp
(配套 README)——
仓库 p03/ 的 wiki 抓取内容没有 QSS,这是本轮补写的教学补充示例,已离屏验证跑通。
模块 B · 练习 95min(计算器案例,练习任务,非预建方案)
button_creation.cpp(数字/运算符按钮)+ custom_signal_slot.cpp
(点击信号槽)+ custom_widget.cpp(布局排布按钮),做出一个能加减乘除的最小计算器QLabel/QLineEdit 上正确显示结果;
界面不重叠、按钮可点击background-color;至少 1 个按钮有
:hover 或 :pressed 效果QT_QPA_PLATFORM=offscreen tools/run_qt.sh <target>
# 有 X 环境:去掉 QT_QPA_PLATFORM=offscreen 直接看窗口
现场演示计算器,至少完成一次正确运算 + QSS 美化。
明天 Day3:高级控件 Model/View / 事件机制 / 文件 IO 与 JSON —— 大纲:docs/teaching/OUTLINE.md