第三章 用户界面设计基础:PyQt5基础、主窗口设计、菜单栏与工具栏、状态栏设计、布局管理

做上位机开发这么多年,我越来越觉得一个道理:界面是软件的「脸面」。你算法再牛,数据再准,用户一打开软件看到乱七八糟的布局,心里就先凉了半截。今天咱们就来聊聊热成像系统上位机的界面设计基础,用的工具是PyQt5。

3.1 PyQt5基础:为什么选它?

说实话,Python的GUI库不少,Tkinter、wxPython、PySide……但我个人最常用的是PyQt5。原因很简单:成熟、稳定、文档全。而且Qt Designer拖拽式设计界面,对咱们做工业软件的来说,效率提升不是一星半点。

先看一个最简单的PyQt5程序骨架:

import sys
from PyQt5.QtWidgets import QApplication, QWidget

app = QApplication(sys.argv)
window = QWidget()
window.setWindowTitle('热成像系统 - 基础窗口')
window.resize(800, 600)
window.show()
sys.exit(app.exec_())

这段代码干了什么?创建了一个应用实例,一个窗口,设置标题和大小,然后显示出来。嗯,就这么简单。但别小看这几行,它是所有复杂界面的起点。

我的习惯:每次新建项目,我都会先跑通这个最小示例。确保环境没问题,再往上堆功能。别一上来就写几百行,调试起来头疼。

3.2 主窗口设计:QMainWindow才是主角

刚才那个QWidget太简陋了。真正做上位机,我们用的是QMainWindow。它自带菜单栏、工具栏、状态栏、中央部件区——说白了,就是给你搭好了骨架,你往里填肉就行。

from PyQt5.QtWidgets import QMainWindow, QLabel

class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle('热成像上位机 v1.0')
        self.resize(1200, 800)
        
        # 中央部件
        central_label = QLabel('热成像画面将显示在这里')
        central_label.setAlignment(Qt.AlignCenter)
        self.setCentralWidget(central_label)

我在项目中遇到过一个问题:有人直接把所有控件都塞到QMainWindow里,结果菜单栏和工具栏一加,布局全乱了。记住,中央部件区才是你放主要内容的地方,菜单栏、工具栏、状态栏都是「外围设施」。

3.3 菜单栏与工具栏:用户的操作入口

菜单栏和工具栏,说白了就是用户和软件交互的「快捷键」。热成像系统里,常见的菜单有:文件(打开、保存、导出)、设备(连接、断开、设置)、视图(全屏、缩放)、帮助(关于)。

def create_menu(self):
    menubar = self.menuBar()
    
    # 文件菜单
    file_menu = menubar.addMenu('文件(&F)')
    file_menu.addAction('打开图像', self.open_image)
    file_menu.addAction('保存截图', self.save_screenshot)
    file_menu.addSeparator()
    file_menu.addAction('退出', self.close)
    
    # 设备菜单
    device_menu = menubar.addMenu('设备(&D)')
    device_menu.addAction('连接热像仪', self.connect_device)
    device_menu.addAction('断开连接', self.disconnect_device)

def create_toolbar(self):
    toolbar = self.addToolBar('主工具栏')
    toolbar.addAction('开始采集', self.start_acquisition)
    toolbar.addAction('停止采集', self.stop_acquisition)
    toolbar.addSeparator()
    toolbar.addAction('温度分析', self.temp_analysis)
避坑指南:我曾经把工具栏图标做得特别花哨,结果在客户工控机上显示不出来——因为那台机器没装图标主题。后来我改用内置的QStyle.StandardPixmap图标,或者直接用文字按钮,兼容性好了很多。

3.4 状态栏设计:给用户一点「反馈」

状态栏这东西,很多人觉得可有可无。但做工业软件,状态栏是用户判断系统是否「活着」的重要依据。热像仪连上了吗?帧率多少?温度范围多少?这些信息放状态栏最合适。

def create_statusbar(self):
    self.statusBar().showMessage('就绪', 5000)  # 显示5秒
    
    # 永久部件
    self.connection_label = QLabel('设备: 未连接')
    self.fps_label = QLabel('帧率: 0 FPS')
    self.temp_range_label = QLabel('温度范围: -- ~ --')
    
    self.statusBar().addPermanentWidget(self.connection_label)
    self.statusBar().addPermanentWidget(self.fps_label)
    self.statusBar().addPermanentWidget(self.temp_range_label)

你想想看,用户盯着屏幕看热成像图,突然画面卡住了。他第一反应是看状态栏——帧率是不是掉到0了?设备是不是断连了?状态栏就是软件的「仪表盘」,别让它空着。

3.5 布局管理:别让控件「打架」

这是新手最容易翻车的地方。PyQt5提供了几种布局:QHBoxLayout(水平)、QVBoxLayout(垂直)、QGridLayout(网格)、QFormLayout(表单)。

热成像系统的典型布局是这样的:

  • 左侧:参数控制面板(温度范围、调色板、报警设置)
  • 中央:热成像画面显示区(占大部分空间)
  • 右侧:实时数据面板(最高温、最低温、平均温、温度曲线)
  • 底部:状态栏
def setup_layout(self):
    # 主布局:水平
    main_layout = QHBoxLayout()
    
    # 左侧控制面板
    left_panel = QVBoxLayout()
    left_panel.addWidget(QLabel('温度范围'))
    left_panel.addWidget(self.temp_min_spin)
    left_panel.addWidget(self.temp_max_spin)
    left_panel.addWidget(QLabel('调色板'))
    left_panel.addWidget(self.palette_combo)
    left_panel.addStretch()  # 弹簧,把控件顶到上面
    
    # 中央画面
    center_widget = QLabel('热成像画面')
    center_widget.setAlignment(Qt.AlignCenter)
    center_widget.setStyleSheet('background-color: black;')
    
    # 右侧数据面板
    right_panel = QVBoxLayout()
    right_panel.addWidget(QLabel('实时数据'))
    right_panel.addWidget(self.max_temp_label)
    right_panel.addWidget(self.min_temp_label)
    right_panel.addWidget(self.avg_temp_label)
    
    # 组装
    main_layout.addLayout(left_panel, 1)   # 比例1
    main_layout.addWidget(center_widget, 3) # 比例3
    main_layout.addLayout(right_panel, 1)   # 比例1
    
    # 设置到中央部件
    central_widget = QWidget()
    central_widget.setLayout(main_layout)
    self.setCentralWidget(central_widget)
核心原则:布局嵌套不要超过3层。超过3层,代码可读性急剧下降,调试起来想砸电脑。如果确实需要复杂布局,考虑用QStackedWidgetQTabWidget分页显示。

3.6 知识体系总览

下面这张图,是我自己总结的PyQt5界面设计知识体系。你可以把它当作「地图」,学完本章后对照着检查自己掌握了多少。

PyQt5 用户界面设计知识体系 QMainWindow 主窗口 菜单栏 (QMenuBar) 文件 | 设备 | 视图 | 帮助 工具栏 (QToolBar) 开始采集 | 停止 | 分析 状态栏 (QStatusBar) 连接状态 | 帧率 | 温度 布局管理 (Layout) QHBoxLayout QVBoxLayout QGridLayout QFormLayout 中央部件 (Central Widget)

这张图把本章的核心内容串起来了。你从QMainWindow出发,往四个方向延伸:菜单栏、工具栏、状态栏、布局管理。中央部件是「画板」,布局是「画笔」,菜单和工具栏是「颜料盒」,状态栏是「画布状态指示器」。嗯,这么一比喻,是不是好记多了?

我的建议:初学者先别急着写代码。打开Qt Designer,拖几个控件试试,看看布局怎么自动调整。玩明白了,再手写代码。我当年就是这么过来的,效率高很多。

好了,这一章的内容就到这儿。界面设计是门手艺活,多练、多改、多问「用户看到这个会怎么想」,慢慢就有感觉了。


公众号:蓝海资料掘金营,微信deep3321