4、地面站 UI 布局设计:从零搭一个看得过去的界面
做地面站,说白了就是给无人机造一个驾驶舱。你想想看,飞手盯着屏幕,要同时看高度、速度、地图、电池电量……信息一多,布局就特别容易乱。我早期做过一个原型,把所有控件堆在一个窗口里,结果自己调试时都找不到按钮在哪。嗯,那体验,别提多糟了。
今天我们就来聊聊,怎么用 Qt 的布局系统,搭一个既专业又清爽的地面站主界面。我会把我在几个项目里踩过的坑、总结的经验,一并倒出来。
4.1 布局三剑客:QVBoxLayout / QHBoxLayout / QGridLayout
Qt 的布局管理器,说白了就是帮你自动排控件的。你不需要手动算坐标,窗口缩放时它们会自动调整。我个人习惯,先把大框架定下来,再往里填细节。
4.1.1 QVBoxLayout:垂直堆叠
适合放从上到下的信息流。比如左侧的飞行数据面板,高度、速度、GPS 状态,一条条往下排。
QVBoxLayout *vLayout = new QVBoxLayout;
vLayout->addWidget(altitudeLabel);
vLayout->addWidget(speedLabel);
vLayout->addWidget(gpsStatusLabel);
vLayout->addStretch(); // 弹簧,把控件顶到上面
setLayout(vLayout);
addStretch(),不然控件会挤在一起。我曾经忘了加,结果窗口拉大时,三个标签贴在天花板上,下面空一大片,特别丑。
4.1.2 QHBoxLayout:水平排列
适合放并排的控件。比如地图和视频流,左右分屏。
QHBoxLayout *hLayout = new QHBoxLayout;
hLayout->addWidget(mapWidget, 2); // 地图占2份
hLayout->addWidget(videoWidget, 1); // 视频占1份
hLayout->setSpacing(5); // 控件间距5像素
这里有个坑:拉伸因子(那个数字 2 和 1)决定了控件在窗口缩放时的比例。我建议地图给大一点,毕竟飞手主要看地图。
4.1.3 QGridLayout:网格布局
适合做仪表盘。比如把姿态仪、罗盘、电池状态排成 2x2 的格子。
QGridLayout *grid = new QGridLayout;
grid->addWidget(attitudeIndicator, 0, 0); // 第0行第0列
grid->addWidget(compass, 0, 1); // 第0行第1列
grid->addWidget(batteryWidget, 1, 0); // 第1行第0列
grid->addWidget(radioWidget, 1, 1); // 第1行第1列
grid->setAlignment(compass, Qt::AlignCenter);
4.2 多标签页:用 QTabWidget 管理信息层级
地面站的信息太多了,全堆在一个页面里,飞手会疯掉。QTabWidget 就是用来做分页的。我一般分三个标签页:飞行数据、地图、设置。
QTabWidget *tabWidget = new QTabWidget;
tabWidget->addTab(flightDataPage, "飞行数据");
tabWidget->addTab(mapPage, "地图");
tabWidget->addTab(settingsPage, "设置");
tabWidget->setCurrentIndex(0); // 默认显示第一个标签
你想想看,飞手在飞行中主要看「飞行数据」和「地图」,设置一般在地面调好就不动了。所以我把前两个标签放在前面,第三个放后面。
4.3 可停靠面板:QDockWidget 的灵活用法
QDockWidget 是 Qt 里最灵活的东西。它可以让用户把面板拖来拖去,停靠在主窗口的上下左右。我特别喜欢这个功能,因为不同飞手有不同习惯——有人喜欢把日志面板放右边,有人喜欢放下面。
QDockWidget *dock = new QDockWidget("日志", this);
dock->setWidget(logWidget);
dock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
addDockWidget(Qt::RightDockWidgetArea, dock);
这里要注意:setAllowedAreas 限制了面板能停靠的位置。我一般只允许左右停靠,因为上下停靠会压缩地图的高度,影响视野。
4.4 设计一个简洁的主界面原型
好了,理论说完了,我们来拼一个实际的原型。下面是我常用的布局方案:
// 主窗口
QMainWindow *mainWindow = new QMainWindow;
// 中央区域:用 QTabWidget 放地图和飞行数据
QTabWidget *centerTabs = new QTabWidget;
centerTabs->addTab(mapWidget, "地图");
centerTabs->addTab(flightDataWidget, "飞行数据");
mainWindow->setCentralWidget(centerTabs);
// 左侧:可停靠的仪表盘
QDockWidget *instrumentDock = new QDockWidget("仪表盘", mainWindow);
instrumentDock->setWidget(instrumentPanel);
instrumentDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
mainWindow->addDockWidget(Qt::LeftDockWidgetArea, instrumentDock);
// 右侧:可停靠的日志面板
QDockWidget *logDock = new QDockWidget("日志", mainWindow);
logDock->setWidget(logWidget);
logDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
mainWindow->addDockWidget(Qt::RightDockWidgetArea, logDock);
这个原型的好处是:
- 中央区域是核心,地图和飞行数据一键切换
- 左侧仪表盘显示姿态、高度、速度等实时数据
- 右侧日志显示串口输出、错误信息
- 所有面板都可以拖拽,用户自己调整
4.5 本章知识体系图
下面我用一张 SVG 图,把今天讲的布局逻辑串起来。你可以把它当作设计时的参考框架。
这张图展示了一个典型的地面站布局:左右可停靠面板 + 中央标签页。你可以在实际项目中,根据需求调整面板数量和位置。
4.6 小结
今天的内容,说白了就是三件事:
- 用布局管理器(QVBoxLayout / QHBoxLayout / QGridLayout)把控件排整齐
- 用 QTabWidget 把信息分页,避免界面爆炸
- 用 QDockWidget 给用户自由,让面板可拖拽
我个人觉得,地面站的 UI 设计,70% 的功夫在布局,30% 在美化。先把布局搞顺了,后面加样式表(QSS)才事半功倍。嗯,下一节我们会聊怎么用 QSS 给地面站「化妆」,让它看起来更专业。
可可精品资料库