v1.1.1: 修复编译流程 — 弹窗先行 & 按钮锁死

【交互优化】
- 编译对话框在点击按钮后立刻弹出,不再先干等再弹窗
- 对话框内分阶段展示进度:保存 → 清理 → 生成CMake → CMake配置 → 编译
- 每阶段通过 processEvents() 保持界面响应
- 编译按钮在编译期间锁死(显示🔒),关闭弹窗后自动解锁
- 关闭按钮在编译完成前禁用,防止中途关闭导致状态异常
- CMake 配置失败时也显示详细错误信息
This commit is contained in:
虾哥
2026-04-28 18:41:52 +08:00
parent 1f7328174b
commit d86bbb35d8
2 changed files with 87 additions and 29 deletions

View File

@@ -1,4 +1,5 @@
#include "mainwindow.h" #include "mainwindow.h"
#include <QApplication>
#include <QMenuBar> #include <QMenuBar>
#include <QMenu> #include <QMenu>
#include <QAction> #include <QAction>
@@ -76,12 +77,14 @@ void MainWindow::setupUI()
debugBtn->setStyleSheet("QPushButton { background: #00838F; color: white; font-weight: bold; border: none; border-radius: 4px; padding: 6px 16px; }"); debugBtn->setStyleSheet("QPushButton { background: #00838F; color: white; font-weight: bold; border: none; border-radius: 4px; padding: 6px 16px; }");
connect(debugBtn, &QPushButton::clicked, this, &MainWindow::compileDebug); connect(debugBtn, &QPushButton::clicked, this, &MainWindow::compileDebug);
actionLayout->addWidget(debugBtn); actionLayout->addWidget(debugBtn);
this->debugBtn = debugBtn;
QPushButton *releaseBtn = new QPushButton("🚀 编译 Release"); QPushButton *releaseBtn = new QPushButton("🚀 编译 Release");
releaseBtn->setMinimumHeight(35); releaseBtn->setMinimumHeight(35);
releaseBtn->setStyleSheet("QPushButton { background: #AD1457; color: white; font-weight: bold; border: none; border-radius: 4px; padding: 6px 16px; }"); releaseBtn->setStyleSheet("QPushButton { background: #AD1457; color: white; font-weight: bold; border: none; border-radius: 4px; padding: 6px 16px; }");
connect(releaseBtn, &QPushButton::clicked, this, &MainWindow::compileRelease); connect(releaseBtn, &QPushButton::clicked, this, &MainWindow::compileRelease);
actionLayout->addWidget(releaseBtn); actionLayout->addWidget(releaseBtn);
this->releaseBtn = releaseBtn;
actionLayout->addStretch(); actionLayout->addStretch();
@@ -782,41 +785,23 @@ void MainWindow::compileRelease()
void MainWindow::compileProject(const QString &buildType) void MainWindow::compileProject(const QString &buildType)
{ {
// 先保存工程 // 先校验
if (!saveProject()) {
return;
}
if (currentFilePath.isEmpty()) { if (currentFilePath.isEmpty()) {
QMessageBox::warning(this, "警告", "请先保存工程!"); QMessageBox::warning(this, "警告", "请先保存工程!");
return; return;
} }
QString projectDir = QFileInfo(currentFilePath).absolutePath(); QString projectDir = QFileInfo(currentFilePath).absolutePath();
QString buildDir = projectDir + "/build";
// 删除旧的 build 目录 // ★ 第一时间弹窗,让用户知道开始工作了
QDir buildPath(buildDir);
if (buildPath.exists()) {
buildPath.removeRecursively();
}
buildPath.mkpath(buildDir);
// 生成 CMake
QString cmakePath = projectDir + "/CMakeLists.txt";
if (!cmakeGenerator->generate(config, cmakePath)) {
QMessageBox::critical(this, "错误", "生成 CMake 失败!");
return;
}
// 创建编译信息对话框
QDialog *compileDialog = new QDialog(this); QDialog *compileDialog = new QDialog(this);
compileDialog->setWindowTitle("编译 " + buildType); compileDialog->setWindowTitle("编译 " + buildType);
compileDialog->resize(800, 600); compileDialog->resize(800, 600);
compileDialog->setAttribute(Qt::WA_DeleteOnClose);
QVBoxLayout *dialogLayout = new QVBoxLayout(compileDialog); QVBoxLayout *dialogLayout = new QVBoxLayout(compileDialog);
QLabel *titleLabel = new QLabel("🔨 编译 " + buildType + "..."); QLabel *titleLabel = new QLabel("🔨 正在准备编译 " + buildType + "...");
titleLabel->setStyleSheet("font-size: 18px; font-weight: bold; color: #333;"); titleLabel->setStyleSheet("font-size: 18px; font-weight: bold; color: #333;");
dialogLayout->addWidget(titleLabel); dialogLayout->addWidget(titleLabel);
@@ -829,16 +814,69 @@ void MainWindow::compileProject(const QString &buildType)
QPushButton *closeBtn = new QPushButton("❌ 关闭"); QPushButton *closeBtn = new QPushButton("❌ 关闭");
closeBtn->setMinimumHeight(35); closeBtn->setMinimumHeight(35);
closeBtn->setStyleSheet("QPushButton { background: #C62828; color: white; font-weight: bold; font-size: 14px; border: none; border-radius: 4px; padding: 6px 16px; }"); closeBtn->setStyleSheet("QPushButton { background: #C62828; color: white; font-weight: bold; font-size: 14px; border: none; border-radius: 4px; padding: 6px 16px; }");
closeBtn->setEnabled(false); // 编译未完成时不可关闭
dialogLayout->addWidget(closeBtn); dialogLayout->addWidget(closeBtn);
compileDialog->show(); // ★ 锁死编译按钮
debugBtn->setEnabled(false);
debugBtn->setText("🔒 编译中...");
releaseBtn->setEnabled(false);
releaseBtn->setText("🔒 编译中...");
// 执行 cmake // 弹窗关闭时解锁按钮
outputEdit->append("📋 正在配置 CMake...\n"); connect(compileDialog, &QDialog::finished, this, [this]() {
debugBtn->setEnabled(true);
debugBtn->setText("🐛 编译 Debug");
releaseBtn->setEnabled(true);
releaseBtn->setText("🚀 编译 Release");
});
compileDialog->show();
QApplication::processEvents(); // 立即渲染弹窗
// ===== 阶段 1保存工程 =====
outputEdit->append("💾 正在保存工程配置...");
if (!saveProject()) {
outputEdit->append("❌ 保存失败!");
titleLabel->setText("❌ 保存失败");
titleLabel->setStyleSheet("font-size: 18px; font-weight: bold; color: #f44336;");
closeBtn->setEnabled(true);
return;
}
outputEdit->append("✅ 工程已保存\n");
QApplication::processEvents();
// ===== 阶段 2清理旧 build =====
QString buildDir = projectDir + "/build";
outputEdit->append("🧹 正在清理旧的构建目录...");
QDir buildPath(buildDir);
if (buildPath.exists()) {
buildPath.removeRecursively();
outputEdit->append("✅ 已删除旧 build 目录\n");
} else {
outputEdit->append("✅ build 目录不存在,跳过清理\n");
}
buildPath.mkpath(buildDir);
QApplication::processEvents();
// ===== 阶段 3生成 CMakeLists.txt =====
outputEdit->append("📄 正在生成 CMakeLists.txt...");
QString cmakePath = projectDir + "/CMakeLists.txt";
if (!cmakeGenerator->generate(config, cmakePath)) {
outputEdit->append("❌ 生成 CMake 失败!");
titleLabel->setText("❌ CMake 生成失败");
titleLabel->setStyleSheet("font-size: 18px; font-weight: bold; color: #f44336;");
closeBtn->setEnabled(true);
return;
}
outputEdit->append("✅ CMakeLists.txt 已生成\n");
QApplication::processEvents();
// ===== 阶段 4CMake 配置 =====
outputEdit->append("📋 正在配置 CMake...");
QProcess cmakeProcess; QProcess cmakeProcess;
cmakeProcess.setWorkingDirectory(buildDir); cmakeProcess.setWorkingDirectory(buildDir);
// 跨平台Windows 必须指定 MinGW Makefiles 生成器
QStringList cmakeArgs; QStringList cmakeArgs;
#ifdef Q_OS_WIN32 #ifdef Q_OS_WIN32
cmakeArgs << "-G" << "MinGW Makefiles" << "-DCMAKE_BUILD_TYPE=" + buildType << ".."; cmakeArgs << "-G" << "MinGW Makefiles" << "-DCMAKE_BUILD_TYPE=" + buildType << "..";
@@ -848,14 +886,30 @@ void MainWindow::compileProject(const QString &buildType)
cmakeProcess.start("cmake", cmakeArgs); cmakeProcess.start("cmake", cmakeArgs);
cmakeProcess.waitForFinished(30000); cmakeProcess.waitForFinished(30000);
outputEdit->append(cmakeProcess.readAllStandardOutput()); QString cmakeOutput = cmakeProcess.readAllStandardOutput();
if (!cmakeOutput.isEmpty()) {
outputEdit->append(cmakeOutput);
}
QString cmakeError = cmakeProcess.readAllStandardError(); QString cmakeError = cmakeProcess.readAllStandardError();
if (!cmakeError.isEmpty()) { if (!cmakeError.isEmpty()) {
outputEdit->append("⚠️ CMake 警告/错误:\n" + cmakeError); outputEdit->append("⚠️ CMake 警告/错误:\n" + cmakeError);
} }
// 执行构建跨平台Windows 用 mingw32-makeLinux/macOS 用 make if (cmakeProcess.exitCode() != 0) {
outputEdit->append("\n🔨 正在编译 " + buildType + "...\n"); outputEdit->append("\n❌ CMake 配置失败!错误代码:" + QString::number(cmakeProcess.exitCode()));
titleLabel->setText("❌ CMake 配置失败");
titleLabel->setStyleSheet("font-size: 18px; font-weight: bold; color: #f44336;");
closeBtn->setEnabled(true);
return;
}
outputEdit->append("✅ CMake 配置完成\n");
QApplication::processEvents();
// ===== 阶段 5编译 =====
outputEdit->append("🔨 正在编译 " + buildType + "...\n");
titleLabel->setText("🔨 编译 " + buildType + " 中...");
QApplication::processEvents();
QProcess makeProcess; QProcess makeProcess;
makeProcess.setWorkingDirectory(buildDir); makeProcess.setWorkingDirectory(buildDir);
@@ -889,6 +943,8 @@ void MainWindow::compileProject(const QString &buildType)
titleLabel->setStyleSheet("font-size: 18px; font-weight: bold; color: #f44336;"); titleLabel->setStyleSheet("font-size: 18px; font-weight: bold; color: #f44336;");
} }
// ★ 编译完成,允许关闭和重新编译
closeBtn->setEnabled(true);
connect(closeBtn, &QPushButton::clicked, compileDialog, &QDialog::accept); connect(closeBtn, &QPushButton::clicked, compileDialog, &QDialog::accept);
} }

View File

@@ -91,6 +91,8 @@ private:
QPushButton *saveButton; QPushButton *saveButton;
QPushButton *generateButton; QPushButton *generateButton;
QPushButton *debugBtn;
QPushButton *releaseBtn;
// 配置和生成器 // 配置和生成器
ProjectConfig *config; ProjectConfig *config;