教学示例补 5 个:3 个坑点复现 + QTableWidget + Day5 学员管理器参考实现
- pitfall_stack_widget / pitfall_lambda_capture / pitfall_double_connect: 默认跑正确写法(离屏验证退出码 0),--crash / --dangle 开关课堂现场触发 真实崩溃/悬空访问 - table_widget:QTableWidget 单元格事件最小示例(新安排 Day4「表格事件」) - student_manager:Day5 综合案例参考实现,离屏自测覆盖 JSON round-trip 与 QThread 后台导入闭环 - 均接入 examples/CMakeLists.txt 的 add_teaching_example,手工维护区不影响生成器
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
// ============================================================================
|
||||
// qt_table_widget_basics —— 教学补充示例:QTableWidget 表格与单元格事件
|
||||
// 对应教案:OUTLINE_4DAY.md Day4 上午「表格」环节(新安排原文「表格事件」)
|
||||
// 配套文档:docs/teaching/examples/table_widget/README.md
|
||||
// 离屏验证:QT_QPA_PLATFORM=offscreen tools/run_qt.sh qt_table_widget_basics
|
||||
//
|
||||
// QTableWidget 是「item 类」控件:数据直接塞进控件里(QTableWidgetItem),
|
||||
// 上手快、够中小项目用;数据/展示彻底分离的完整 Model/View 架构见
|
||||
// ../model_view/qt_model_view_basics.cpp(延伸钩子)。
|
||||
// ============================================================================
|
||||
|
||||
#include <QApplication>
|
||||
#include <QHeaderView>
|
||||
#include <QLabel>
|
||||
#include <QTableWidget>
|
||||
#include <QTimer>
|
||||
#include <QVBoxLayout>
|
||||
#include <QWidget>
|
||||
|
||||
class TableDemo : public QWidget {
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit TableDemo(QWidget* parent = nullptr) : QWidget(parent) {
|
||||
m_table = new QTableWidget(3, 3, this); // 行列数在构造时给定
|
||||
m_table->setHorizontalHeaderLabels(
|
||||
{QStringLiteral("姓名"), QStringLiteral("成绩"), QStringLiteral("标签")});
|
||||
m_table->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
|
||||
|
||||
const char* names[] = {"张三", "李四", "王五"};
|
||||
const char* scores[] = {"91.5", "88", "76"};
|
||||
const char* tags[] = {"组长", "美工", "测试"};
|
||||
for (int row = 0; row < 3; ++row) {
|
||||
// 每个单元格一个 QTableWidgetItem,new 出来交给表格接管所有权
|
||||
m_table->setItem(row, 0, new QTableWidgetItem(QString::fromUtf8(names[row])));
|
||||
m_table->setItem(row, 1, new QTableWidgetItem(QString::fromUtf8(scores[row])));
|
||||
m_table->setItem(row, 2, new QTableWidgetItem(QString::fromUtf8(tags[row])));
|
||||
}
|
||||
|
||||
m_status = new QLabel(QStringLiteral("点击任意单元格试试"), this);
|
||||
|
||||
auto* layout = new QVBoxLayout(this);
|
||||
layout->addWidget(m_table);
|
||||
layout->addWidget(m_status);
|
||||
|
||||
// 「表格事件」以信号形式暴露:cellClicked / cellDoubleClicked /
|
||||
// itemChanged(编辑单元格后触发)…… 不需要重写 event 函数。
|
||||
connect(m_table, &QTableWidget::cellClicked, this, &TableDemo::onCellClicked);
|
||||
connect(m_table, &QTableWidget::itemChanged, this, [this](QTableWidgetItem* item) {
|
||||
m_status->setText(QStringLiteral("(%1,%2) 被改为 %3")
|
||||
.arg(item->row()).arg(item->column()).arg(item->text()));
|
||||
});
|
||||
}
|
||||
|
||||
private slots:
|
||||
void onCellClicked(int row, int column) {
|
||||
QTableWidgetItem* item = m_table->item(row, column);
|
||||
m_status->setText(QStringLiteral("点击了 (%1,%2):%3")
|
||||
.arg(row).arg(column)
|
||||
.arg(item ? item->text() : QStringLiteral("<空>")));
|
||||
}
|
||||
|
||||
private:
|
||||
QTableWidget* m_table = nullptr;
|
||||
QLabel* m_status = nullptr;
|
||||
};
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
QApplication app(argc, argv);
|
||||
TableDemo demo;
|
||||
demo.setWindowTitle(QStringLiteral("QTableWidget 基础"));
|
||||
demo.resize(420, 240);
|
||||
demo.show();
|
||||
|
||||
if (qgetenv("QT_QPA_PLATFORM") == "offscreen") {
|
||||
QTimer::singleShot(200, &app, &QApplication::quit);
|
||||
}
|
||||
return app.exec();
|
||||
}
|
||||
|
||||
#include "qt_table_widget_basics.moc"
|
||||
Reference in New Issue
Block a user