王晓辉 聂小华 常 亮
(中国飞机强度研究所 陕西 西安 710065)
随着信息技术的发展,以有限元法[1]为主体的分析技术已成为产品结构设计过程中进行强度分析与性能评定的标准流程之一。按照工业软件的适用范围和功能需求来说,有限元软件包含两大类:通用软件和专用软件。其中通用有限元软件大多属于商业软件,不仅价格昂贵和技术封锁,且在实际应用中需要通过二次开发和不定期投资维护,因而开发自主产权的专用有限元软件成为当下适合工程应用和规避科研风险的必然选择。在功能划分和组成方面,有限元软件包含三部分:前处理、求解器和后处理。在整个分析过程中,前后处理占据了80%的时间,包括有限元模型的构建、物理属性的定义及模型的可视化分析,整个过程紧密融合了用户的需求。通过调研发现,目前国内外对于专用有限元软件的开发,大多数集中于求解算法效率的提升和计算理论的推导等方面,而忽视了软件用户界面的友好交互性。设计一个友好交互的面向工程需求的图形用户界面GUI,将给有限元分析的前后处理工作带来极大的方便,大大改善软件的整体性能。GUI模块作为开发其他专用软件的起点,在软件设计开发过程中扮演重要角色[2]。
传统的有限元软件开发往往更关注软件功能的实现而忽略了软件的用户体验。但随着计算机软硬件技术的飞速发展,用户对于有限元软件的可操作性、扩展性、跨平台性、美观性等方面提出了更高的要求。从而软件用户界面的设计也越来越受到开发人员的重视,但具体实现中难度也很大。比如ANSYS等商业软件,每几年都会通过用户体验反馈,进行版本提升,但提供的用户界面至今仍未令人很满意[3],尤其是在用户友好性方面存在一定的局限性。再如主流的PATRAN、ABAQUS CAE等软件,虽然拥有众多的用户群体,但由于特有的用户界面设计,固化了用户的使用习惯,使得国内工程应用依赖于国外软件,一定程度上阻碍了国产自主CAE软件的发展和推广。在国内,早期的国内学者对软件用户界面的设计更多聚焦于界面设计原则和方法理论的阐述[4],对于程序实现层面的描述不是很多。对于有限元软件的用户界面的开发形式大致包括:基于商业软件二次开发[5]、开源程序的封装集成和[6-7]和针对特定应用场景的用户界面程序设计与开发[8-10]。其中二次开发和开源程序封装入门难度较大,开发成本较高;特定功能的软件用户界面设计开发需求明确,更能满足用户和计算系统多方面的要求。因此,通过自主开发构建跨平台的友好的专用有限元软件的图形用户界面成为了国产有限元软件开发的最佳选择。
经过调研发现,目前主流的GUI设计工具有MFC、Qt、wxWidget以及Gnome。其中MFC和Gnome不能跨平台,不可移植。真正跨平台的只有Qt和wxWidget,但是wxWidget目前缺乏专业维护和技术支持,无法满足客户需求。Qt作为一个非常优秀的面向对象的跨平台图形开发框架,有很强的扩展性,支持组件编程[12]。为此,本文结合航空结构强度分析流程,以用户需求为中心[13-14],采用多窗口界面(MDI)设计方式,基于Qt技术在Windows操作系统下进行专用有限元软件用户界面的设计与开发,最后结合HAJIF基础求解平台验证应用。
HAJIF全名为航空结构强度分析与优化设计软件系统,它是由中国飞机强度研究所历经了多年艰辛探索与突破,研制推出的一款国内航空领域功能最完善的自主CAE软件系统,涵盖了飞行器结构分析、优化设计、气动弹性和强度校核等多种功能。尤其在最近几年,HAJIF计算系统在求解规模效率方面有了很大提升,已广泛应用于航空、航天、交通和武器装备等领域[15-19]。
鉴于有限元软件主要解决和分析大而复杂的科学和工程问题,具有复杂和异构的数据类型,从而要求其对用户界面的设计必须遵循简便性、直接性、可控性、美观性、反馈性、标准化和一致性的原则,同时可面向多层次用户需求。
为了更好地完成用户界面的设计,通过调研当下商业有限元软件界面的元素构成,结合有限元分析流程,有限元软件系统的GUI除了考虑文件的管理、前处理、与求解器的数据关联、后处理结果显示等功能外,还需要添加常用工具、动态语言切换和帮助文档等新的功能。同时,针对有限元软件中多个功能模块之间“高内聚,低耦合”的特性,为了有效降低软件编制的复杂度,提高软件模块的维护性和可移植性,在此采用多窗口界面(MDI) 设计方式,实现单一主窗口和多个子窗口的数据管理[20-21]。其中,有限元软件主界面的总体框架如图1所示。
图1 有限元软件主界面总体框架图
结合有限元分析流程,有限元软件的基本操作步骤如图2所示。在有限元软件操作过程中,用户可实时通过帮助菜单获取帮助信息,通过语言设置菜单实现界面语言动态切换,通过快捷工具栏实现特殊操作功能等。
图2 有限元软件主要操作步骤
根据以上设计思路,可以得到有限元软件主界面中的区域分配和界面元素布局,如图3所示包含主窗口和基本的界面元素,如菜单栏、工具栏、状态栏、数据视窗和模型树等。
图3 有限元软件主界面区域分配和元素布局
本文在设计过程中主要采用Qt和C++作为开发环境。由于软件用户界面存在大量人机交互操作,因此对于数据通信效率有很高的要求。其中Qt的信号槽机制是类型安全且松散耦合的,已逐渐替代了传统的回调函数,使得数据信号的传递更安全高效。此外,Qt 中集合了强大的类库,具有丰富的API,可支持对图形、文本、数据库、网络、I/O及视图控件等的操作。因此在有限元软件用户界面设计中,Qt开发框架能够很好地满足软件多接口、多响应、多元素、个性化设计和后期跨平台应用的需求。
Qt包含了各种功能不同的模块,每个模块都有隶属于自己的类库。其中常用的模块有QtCore(核心模块)、QtGui(GUI模块)、QtNetwork(网络模块)、QtOpenGL(OpenGL 3D模块)、QtScript(脚本模块)、QtXml(文本模块)和QtSql(Sql数据库模块)。在程序实际设计中,主要用到的类包括QObject(Qt 对象模型的基类)、QApplication(界面程序控制和设置类)、QWidget和QDialog(组件容器类)、QMainWindow(中央窗口部件类)、QEvent(Qt事件响应类的基类)和QLayout(布局管理类)等[22]。Qt类库组织结构合理,使用时需要按照各类的集成关系进行操作,本文所用到的Qt类属结构如图4所示。
图4 Qt类结构示意图
软件主界面各个窗口都继承自 QMainWindow类,主要功能是用于程序的运行显示,其上的组件分别包含 CentralWidget、 QToolBar、 QMenuBar等子类,分别对应界面布局、菜单栏和工具栏等的显示。基于以上子类又可以派生出如 QMenu(菜单),QAction(动作)、QGroupBox(组合框)和 QLabel(文本和图的显示)等子类,以实现子窗口中的特殊功能。
在软件使用过程中,用户界面最重要的功能就是处理人与软件之间的信息传递及交互。其中,信号与槽作为Qt框架编程的基础,属于一种观察者模式,用来实现对象间的数据响应和通信,操作简便灵活,从而可以大幅提高软件的人机交互效率。程序调用形式如下:
connect(sender,signal,receiver,slot)
其中:sender是发送信号的对象;signal是发送对象发出的信号;receiver是接收信号的对象;slot是接受对象在接收到信号之后需要执行的功能函数。
在有限元软件系统界面中,除了常规的界面交互功能,还需要提供图形可视化等功能。OpenGL作为绘制三维图形的标准API,在图形可视化方面应用广泛。其中,QtOpenGL模块依赖于OpenGL库,经常被Qt应用程序用来绘制3D图形[23]。在具体实现中,需要对QtOpenGL的QGLWidget类进行子类化,并且需要在QGLWidget中实现场景绘制虚函数,如void initiallizeGL(),void resizeGL()和void paintGL()等,也可以直接调用OpenGL命令开发窗口部件。
软件界面语言的多样化已成为评估软件可用性的重要指标。其中Qt全面使用Unicode,对国际化支持十分成熟。如图5所示,Qt linguist(又称Qt语言家)是Qt的一个附加组件,很好地解决了Qt的国际化问题,方便了程序界面语言的翻译,具体实现在4.4小节有所描述。
图5 Qt linguist
如图6所示,本文介绍的有限元软件界面实现流程图表明,基于Qt的有限元软件界面的应用程序框架是自上向下的。以下重点描述几个重要流程的具体实现过程。
图6 有限元软件界面实现流程图
首先在主函数(main函数)中生成QApplication类的一个实例hjif_app,然后依照功能要求编辑主窗口类MainWindow的实例hjf_mainWin。软件用户界面的主入口程序如下:
int main(int argc, char*argv[])
{
QApplication hjf_app(argc, argv);
//产生一个QApplication类的实例hjf_app,
//可以为开发机构和程序命名
hjf_app.setOrganizationName("机构名称");
hjf_app.setApplicationName("软件名称");
//定义Mainwindow类的对象hjf_mainWin,
//Mainwindow类以公有形式继承QMainwindow类
MainWindow hjf_mainWin;
hjf_mainWin.setMinimumWidth(960);
//设置主窗口最小宽度
hjf_mainWin.setMinimumHeight(600);
//设置主窗口最小高度
hjf_mainWin.showMaximized();
//主窗口最大化
int ret=hjf_app.exec();
//显示主窗口
return ret;
}
如图7所示,有限元软件的用户界面主要包括6部分:(1) 菜单和工具栏,包括模型/结果导入、导出等;(2) 视图控制栏,具有6个视图操作和常规鼠标操作;(3) 模型树/结果树,包含了有限元模型的几何、网格、材料、属性等信息的层次目录;(4) 视图区,作为软件界面中区域最大的部分,为用户提供可视化窗口;(5) 功能窗口,主要作为各个功能模块的数据输入界面以及配置参数选项界面等;(6) 应用窗口部件类,可单独使用,也可以作为功能窗口的子部件被使用。
图7 有限元软件界面组成部分
其中主要功能窗口部件包含对话框(QDialog)、基础窗口部件(QWidget)和其他特殊窗口部件。主界面的程序实现如下:
MainWindow::MainWindow(QWidget*parent):
{
//窗体、对话框初始化
m_importThread=NULL;
//模型导入进程类
m_entityDlg=NULL;
//元素创建窗体
……
languageUpdate();
//更新语言
createMenus();
//创建菜单
createToolBars();
//创建工具栏
createStatusBar();
//创建状态栏
createGuidTree();
//创建向导树:模型树和结果树
iniMainLayout();
//初始化界面布局
showMaximized();
//主窗口最大化
//设置主窗口名称和图标
setWindowTitle(tr("%1%2").arg(TITLE).arg(VER));
setWindowIcon(QIcon(":/public/image/hajifui.png"));
setupSolPath();
//设置求解器路径
setupEnvironment();
//设置环境变量
}
图7中的5-功能窗口的程序实现主要代码如下:
class LoadDlg:public QDialog
{
public:
QLineEdit*m_txtLoadFilePath;
//文本输入框
QRadioButton *m_rdbDisForce;
//单选按钮
QLabel *m_lblOutFormat;
//文本标签
QComboBox *m_cmbOutLoadFormat;
//复选按钮
ApplyEntityWgt *m_applyTargetEntity;
//实体组合部件
};
可以看出,LoadDlg是自定义设计的类,继承自QDialog,其包含的控件有文本标签、文本输入框、单选/复选按钮和应用组合部件。另外,应用组合部件类ApplyEntityWgt也是自定义设计的类,继承自QWidget,对应的是图7中所示的应用窗口部件,程序实现代码如下:
class ApplyEntityWgt:public QWidget
{
public:
QPushButton*m_btnAddMember;
//点击按钮
QTextEdit *m_txtApplicationEntities;
//文本框
};
按照总体布局,在主窗口进行布局,并设置界面的主要通讯机制,程序代码实现如下:
void MainWindow::iniMainLayout()
{
//初始化可视化控件
if (!m_glWidget)
m_glWidget=new GlWidget(this);
setCentralWidget(m_glWidget);
//将视图区至于主窗口中心
//将向导树区置于主窗口靠左区域
addDockWidget(Qt::LeftDockWidgetArea,m_wgtDockTree);
//将结果树控件至于主窗口靠左区域
addDockWidget(Qt::LeftDockWidgetArea,m_resDockWgt);
//将模型树树控件至于主窗口靠左区域
addDockWidget(Qt::LeftDockWidgetArea,m_modelDockWgt);
//将工具栏控件至于主窗口顶部区域
addToolBar(Qt::TopToolBarArea,m_tlbFile);
addToolBar(Qt::TopToolBarArea,m_resultToolBar);
addToolBar(Qt::TopToolBarArea,m_tlbView);
//将元素选择工具栏至于主窗口右部区域
addToolBar(Qt::RightToolBarArea,m_tlbSelect);
//界面操作和视图模块的信号与槽信号关联
connect(m_glWidget,SIGNAL(nodePicked(SW_NODE*,int)),this,SLOT(onNodePicked(SW_NODE*,int)));
connect(m_glWidget,SIGNAL(elementPicked(SW_ELCONN*,int)),this,SLOT(onElementPicked(SW_ELCONN*,int)));
}
有限元软件的操作往往需要工程师的参与和大量的图形交互操作完成,在此使用Qt的信号与槽机制来实现操作对象间的数据通信。图8形象地描述了基于Qt的信号槽机制所创建的有限元软件用户界面事件响应的基本流程。
图8 有限元软件界面交互事件响应流程
在软件界面交互操作中,鼠标和键盘作为关联用户界面动作和视图响应的最主要的输入设备,响应事件主要包括鼠标移动、右键单击、右键双击、左键单击、左键双击、左键按下、左键弹出等。在Qt中,这些鼠标响应事件统一对应于QWidget中的虚拟方法[9],并且不同的鼠标事件具有不同的输入参数。捕获鼠标事件首先会覆盖这些虚拟方法,以便鼠标事件可以在不同组件上发生时调用相应的事件。在实现代码中,所有鼠标双击事件都将调用mouseMoveEvent()函数,必须通过输入参数QMouseEvent * event(left,middle或right)的信息来区分。程序实现的主要代码如下:
void GlWidget::mouseMoveEvent(QMouseEvent*event)
{
QPoint point=event->pos();
Qt::MouseButtons buttons=event->buttons();
if (buttons==Qt::LeftButton)
{ //处理左键单击命令
}
else if (buttons==Qt::MidButton)
{ //处理中键单击命令
}
else if (buttons==Qt::RightButton)
{ //处理右键单击命令
}
else
{ //其他
}
}
最后,实现软件用户界面的语言切换,需要执行以下步骤:
1) 使用tr()完成对用户可见的文本信息的封装;
2) 构建一种用户可执行语言切换的函数方法;
3) 对于主界面中的所有窗口部件,重写系统响应事件changeEvent。
具体程序实现中,首先要创建语言文件ts,然后通过Qt linguist进行翻译,接着编译ts文件生成可直接调用加载的语言文件qm,最后应用QTranslator类加载生成的qm文件,以此来显示程序所指定的语言类型,主要程序如下:
QTranslator translator;
//提供对文本输出的国际化支持
translator.load(":/qm/main_widget_zh");
//加载语言文件
app.installTranslator(&translator);
//整个程序加载翻译文件
若要实现多国语言实时切换,在调用installTranslator方法后,由于各窗体的状态会发生变化,系统则会自动给每个窗体发送信号并告知changeEvent槽event产生,因此要在切换语言的每个窗体中重写changeEvent事件,程序实现如下:
void MainWindow::changeEvent(QEvent*e)
{
QWidget::changeEvent(e);
switch (e->type())
{
case QEvent::LanguageChange:
retranslateUi(this);
break;
default:
break;
}
通过将本文所开发的面向用户的具有友好操作性的专用有限元软件用户界面,与自主有限元计算系统HAJIF进行数据关联,最终实现了软件系统用户界面与分析计算、前后处理及其各功能模块的综合集成,检验了上述开发方法的可行性。以下是基于本文方法所开发的HAJIF系统的几个典型功能的子界面。
如图9所示,通过实现 HAJIF系统的优化设计模块的数据输入界面,大幅提高了优化设计变量的创建效率,精简了数据输入量,改善了用户操作体验。
图9 HAJIF系统优化设计模块的数据输入界面
图10所示为HAJIF系统后处理功能模块显示界面。通过界面鼠标点击三维模型云图上的感兴趣的节点或者单元,就可以实现以对话框和标识的形式进行数据展示,从而完成了有限元分析过程可视化,提高了工程人员在有限元分析过程中的参与感。
图10 HAJIF系统后处理模块数据显示及查询界面
在有限元软件系统的设计开发中,不仅需要满足系统的基本分析功能,更应注重系统的使用功能,即系统必须为用户提供直观、便捷、友好、灵活的用户图形界面,能够满足专用模块的综合集成和个性化定制开发需求。本文通过梳理有限元软件的界面框架,结合有限元分析流程,采用MDI的设计方式,引入Qt图形开发框架,开发出了一种基于Qt的专用有限元软件GUI模块。该模块是针对航空结构强度分析与优化设计软件系统HAJIF设计开发的,但同时也形成了有限元软件GUI模块高效的设计开发方法,除了应用于HAJIF系统,还在一些其他有限元软件中得以应用,从而表明了该GUI模块不仅具备了较高的友好交互性,还极大满足了有限元软件系统高效开发的集成需求。同时由于Qt组件开发的跨平台特性,符合大型有限元软件系统多平台的开发要求,也为专用有限元软件系统集成和定制开发提供了一条可借鉴的途径。