第2章:主框架搭建
好,咱们正式开始动手了。这一章,我们要把EPS软件的骨架搭起来。
说白了,就是创建一个Qt主窗口,把菜单栏、工具栏、状态栏这些标配安排上,再搞定中心部件和配置文件。嗯,这些听起来基础,但基础的东西往往最容易被忽视。我在项目里见过太多人上来就写业务逻辑,结果后面发现窗口结构不合理,改起来那叫一个痛苦。
2.1 创建Qt主窗口
我个人习惯,新建一个Qt项目时,先想清楚主窗口要继承哪个类。对于EPS这种专业软件,QMainWindow是首选。为什么?因为它自带菜单栏、工具栏、状态栏和停靠窗口的支持,省去我们很多手工活。
来看代码:
// MainWindow.h
#include <QMainWindow>
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow();
private:
void setupUI();
void createActions();
void createMenus();
void createToolBars();
void createStatusBar();
void readSettings();
};
注意那个Q_OBJECT宏,新手容易漏掉。漏掉之后信号槽就用不了,编译器也不会报错,运行时才崩溃。我曾经因为这个排查了整整一个下午,后来养成了习惯——写类第一件事就是检查这个宏。
构造函数里,我一般这样写:
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
setupUI();
readSettings();
}
先初始化界面,再读取配置。顺序别搞反了。你想想看,如果先读配置,界面还没创建,配置往哪放?
2.2 菜单栏与工具栏设计
菜单栏是用户操作的第一入口。EPS软件功能多,菜单分类要清晰。我通常这样分:
| 菜单 | 功能 | 示例动作 |
|---|---|---|
| 文件 | 项目文件操作 | 新建、打开、保存、导出 |
| 编辑 | 数据编辑 | 撤销、重做、复制、粘贴 |
| 视图 | 界面布局 | 工具栏、状态栏、全屏 |
| 工具 | 专业功能 | 参数设置、计算、分析 |
| 帮助 | 文档与关于 | 用户手册、版本信息 |
创建菜单的代码很直观:
void MainWindow::createMenus()
{
// 文件菜单
QMenu *fileMenu = menuBar()->addMenu(tr("文件(&F)"));
fileMenu->addAction(tr("新建项目(&N)"), this, &MainWindow::newProject, QKeySequence::New);
fileMenu->addAction(tr("打开项目(&O)"), this, &MainWindow::openProject, QKeySequence::Open);
fileMenu->addSeparator();
fileMenu->addAction(tr("保存(&S)"), this, &MainWindow::saveProject, QKeySequence::Save);
fileMenu->addAction(tr("另存为..."), this, &MainWindow::saveAsProject, QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_S));
fileMenu->addSeparator();
fileMenu->addAction(tr("退出(&X)"), this, &QWidget::close, QKeySequence::Quit);
}
工具栏呢?说白了就是菜单的快捷入口。常用的操作才放工具栏,别什么都往上堆。我见过一个项目,工具栏塞了30多个按钮,用户找功能比翻菜单还费劲。
void MainWindow::createToolBars()
{
QToolBar *fileToolBar = addToolBar(tr("文件"));
fileToolBar->setObjectName("FileToolBar");
fileToolBar->addAction(tr("新建"));
fileToolBar->addAction(tr("打开"));
fileToolBar->addAction(tr("保存"));
// 设置图标
fileToolBar->setIconSize(QSize(24, 24));
fileToolBar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
}
objectName,这样保存窗口状态时能记住用户自定义的布局。用户拖拽调整后,下次打开还是老样子,体验会好很多。
2.3 状态栏与中心部件
状态栏,很多人觉得就是个摆设。其实不然。EPS软件处理数据量大,用户需要实时知道当前状态。我一般放三样东西:
- 左侧:当前操作提示(比如"正在加载项目...")
- 中间:进度信息(比如"处理中:45/100")
- 右侧:永久信息(比如版本号、坐标系)
void MainWindow::createStatusBar()
{
statusBar()->showMessage(tr("就绪"), 3000);
// 添加永久部件
QLabel *versionLabel = new QLabel(tr("v1.0.0"));
versionLabel->setFrameStyle(QFrame::Panel | QFrame::Sunken);
statusBar()->addPermanentWidget(versionLabel);
QLabel *coordLabel = new QLabel(tr("坐标系: WGS84"));
coordLabel->setFrameStyle(QFrame::Panel | QFrame::Sunken);
statusBar()->addPermanentWidget(coordLabel);
}
中心部件,这是主窗口的核心区域。EPS软件通常需要多视图协作,我推荐用QSplitter配合QMdiArea:
void MainWindow::setupCentralWidget()
{
// 创建分割器
QSplitter *splitter = new QSplitter(Qt::Horizontal, this);
// 左侧:项目树
QTreeWidget *projectTree = new QTreeWidget();
projectTree->setHeaderLabel(tr("项目结构"));
// 右侧:多文档区域
QMdiArea *mdiArea = new QMdiArea();
mdiArea->setViewMode(QMdiArea::TabbedView);
splitter->addWidget(projectTree);
splitter->addWidget(mdiArea);
splitter->setStretchFactor(0, 1); // 左侧占1份
splitter->setStretchFactor(1, 3); // 右侧占3份
setCentralWidget(splitter);
}
setStretchFactor。
2.4 应用程序设置与配置文件
配置文件,说白了就是让软件记住用户的偏好。窗口大小、上次打开的文件、工具栏布局,这些都应该保存下来。
Qt提供了QSettings,用起来很方便:
void MainWindow::readSettings()
{
QSettings settings("EPS_Studio", "EPSApp");
// 恢复窗口位置和大小
QByteArray geometry = settings.value("geometry").toByteArray();
if (!geometry.isEmpty()) {
restoreGeometry(geometry);
} else {
resize(1200, 800); // 默认大小
}
// 恢复窗口状态(工具栏、停靠窗口等)
QByteArray state = settings.value("windowState").toByteArray();
if (!state.isEmpty()) {
restoreState(state);
}
// 恢复最近打开的文件
lastFilePath = settings.value("lastFilePath").toString();
}
void MainWindow::writeSettings()
{
QSettings settings("EPS_Studio", "EPSApp");
settings.setValue("geometry", saveGeometry());
settings.setValue("windowState", saveState());
settings.setValue("lastFilePath", lastFilePath);
}
什么时候保存?我建议在关闭事件里做:
void MainWindow::closeEvent(QCloseEvent *event)
{
writeSettings();
QMainWindow::closeEvent(event);
}
- 配置文件路径:Windows在注册表或AppData,Linux在~/.config
- 保存时机:关闭时保存,启动时恢复
- 异常处理:读取失败时用默认值,别让软件崩溃
- 版本兼容:配置格式变化时,要能处理旧版本的数据
嗯,到这里,主框架的骨架就搭好了。你想想看,有了这个基础,后面往里面填功能模块就轻松多了。下一章,咱们开始搞核心的数据模型,那才是EPS软件的真正灵魂。