Day3 教学示例:增强版计算器接入 + QMainWindow/QSS 两版参考实现

- calculator_designer_ext(Day2 增强版:表达式求值 + 括号,递归下降解析器)接入 cmake
- calculator_mainwindow(Day3 上午):增强版计算器装进 QMainWindow,
  菜单/状态栏/历史停靠窗,纯代码 + 显式 connect,与 mainwindow_showcase 形成坑卡对照
- calculator_mainwindow_qss(Day3 下午):上午版 + QSS 双主题美化(按键分色/伪状态/深浅切换)
- 验证 mainwindow_showcase(QMainWindow 六大组件综合演示,.ui + .qrc)
- OUTLINE_4DAY.md / ASSIGNMENTS.md Day3 衔接增强版起点 + 参考实现指引
- 补提交 Day2 calculator/ 与 calculator_designer/ 参考实现(CMakeLists 已引用)
- 全量构建 28/28,4 目标离屏自测退出码 0

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
张宗平
2026-07-07 22:59:05 +08:00
parent ea6f12e7ac
commit 05a685c952
45 changed files with 4599 additions and 6 deletions
@@ -0,0 +1,110 @@
// ============================================================================
// mainwindow_showcase.cpp —— MainWindow 实现(动态行为)
//
// 静态结构见 mainwindow.uiDesigner)。本文件只做:
// - 资源文件应用(5.6):setWindowIcon 从 .qrc 加载
// - 状态栏(5.3):addPermanentWidget + 实时行列/字数 + showMessage 临时提示
// - 信号槽:on_<objectName>_<signal> 自动连接(connectSlotsByName
// - 视图菜单:运行时操控工具栏/状态栏/浮动窗口
// ============================================================================
#include "mainwindow_showcase.h"
#include "ui_mainwindow.h" // AUTOUIC 从 mainwindow.ui 生成
#include <QAction>
#include <QDockWidget>
#include <QIcon>
#include <QLabel>
#include <QMessageBox>
#include <QStatusBar>
#include <QTextCursor>
#include <QTextEdit>
#include <QToolBar>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent), ui(new Ui::MainWindow) {
ui->setupUi(this);
// 5.6 资源文件:应用图标从 mainwindow.qrc 加载(:/icons/app.png
setWindowIcon(QIcon(":/icons/app.png"));
// 5.3 状态栏:永久标签(addPermanentWidget),实时显示光标行列与字数
statusPosLabel = new QLabel(QStringLiteral("行:1 列:1 字数:0"), this);
statusBar()->addPermanentWidget(statusPosLabel);
// 5.5 中心部件 QTextEdit 的内容/光标变化 → 更新状态栏
connect(ui->textEdit, &QTextEdit::textChanged, this, &MainWindow::updateStatusBar);
connect(ui->textEdit, &QTextEdit::cursorPositionChanged, this, &MainWindow::updateStatusBar);
updateStatusBar();
}
MainWindow::~MainWindow() { delete ui; }
// ---- 文件菜单 ----------------------------------------------------------
void MainWindow::on_actionNew_triggered() {
ui->textEdit->clear();
statusBar()->showMessage(QStringLiteral("已新建"), 2000); // 5.3 临时提示
}
void MainWindow::on_actionQuit_triggered() { close(); }
// ---- 视图菜单 —— 运行时操控各组件 --------------------------------------
void MainWindow::on_actionToggleToolBar_toggled(bool checked) {
ui->mainToolBar->setVisible(checked);
}
void MainWindow::on_actionToggleStatusBar_toggled(bool checked) {
statusBar()->setVisible(checked);
}
void MainWindow::on_actionToggleToolBarMovable_toggled(bool checked) {
ui->mainToolBar->setMovable(checked); // 5.2 setMovable
}
void MainWindow::on_actionToggleDockFloating_triggered() {
ui->dockWidget->setFloating(!ui->dockWidget->isFloating()); // 5.4 setFloating
}
void MainWindow::on_actionShowDock_triggered() {
ui->dockWidget->show(); // 5.4 重新显示已关闭的浮动窗口
}
void MainWindow::on_actionHideDock_triggered() {
ui->dockWidget->hide(); // 5.4 关闭(隐藏)浮动窗口
}
void MainWindow::on_actionToolBarAreaLeft_triggered() {
ui->mainToolBar->setAllowedAreas(Qt::LeftToolBarArea); // 5.2 setAllowedAreas
}
void MainWindow::on_actionToolBarAreaRight_triggered() {
ui->mainToolBar->setAllowedAreas(Qt::RightToolBarArea);
}
void MainWindow::on_actionToolBarAreaTop_triggered() {
ui->mainToolBar->setAllowedAreas(Qt::TopToolBarArea);
}
void MainWindow::on_actionToolBarAreaBottom_triggered() {
ui->mainToolBar->setAllowedAreas(Qt::BottomToolBarArea);
}
void MainWindow::on_actionToolBarAreaAll_triggered() {
ui->mainToolBar->setAllowedAreas(Qt::AllToolBarAreas);
}
// ---- 帮助菜单 ----------------------------------------------------------
void MainWindow::on_actionAbout_triggered() {
QMessageBox::about(this, QStringLiteral("关于"),
QStringLiteral(
"<b>QMainWindow 教学综合示例</b><br><br>"
"一个极简文本编辑器,演示 QMainWindow 的六大核心组件"
"wiki「5 QMainWindow」pageId 58954529):<br>"
"5.1 菜单栏 · 5.2 工具栏 · 5.3 状态栏 · "
"5.4 浮动窗口 · 5.5 中心部件 · 5.6 资源文件"));
}
// ---- 状态栏更新 --------------------------------------------------------
void MainWindow::updateStatusBar() {
const QTextCursor c = ui->textEdit->textCursor();
const int line = c.blockNumber() + 1;
const int col = c.columnNumber() + 1;
const int count = ui->textEdit->toPlainText().size();
statusPosLabel->setText(
QStringLiteral("行:%1 列:%2 字数:%3").arg(line).arg(col).arg(count));
}