一杯清酒邀明月
天下本无事,庸人扰之而烦耳。

1.前言

Slicer在Version4之前,GUI使用Kitware公司的GUI工具KWWidget开发,KWWidget不支持Unicode。而Slicer的最新Version4使用了Nokia公司的Qt代替KWWidget进行开发。

2.Slicer界面结构

Slicer应用程序的结构由应用程序核心、Slicer模块组成。
应用程序核心部分实现Slicer用户界面,提供数据输入-输出接口、可视化、拓展应用程序开发界面等。
Slicer模块在整个应用程序中的功能是提供图像处理算法,其输入一般是未经处理的二维/三维图像数据,经过模块提供的图像处理算法处理后输出。

2.1 核心部分

核心部分包括:Slicer的主菜单、工具栏、设置界面、三维视图界面、三个切片视图及其他们的控制界面。Slicer的应用程序界面如上图所示。

2.2 模块部分

包含所有的模块界面,分为三类:可加载模块、命令行模块、脚本模块。
  • 可加载模块界面丰富也很复杂,因为可加载模块的界面元素由UI文件直接定义。

3.Slicer平台界面创建过程研究

由上可知Slicer平台界面由两大部分组成。其中对于模块部分,三种模块之间也是有区别的,造成这种区别的根本原因是程序创建界面的过程不同。

3.1 核心部分

核心部分界面就是主窗口,主要包括主菜单、工具栏、设置界面、三维视图界面、切片视图及其控制界面。
  • 主菜单在创建主窗口的UI文件中创建,采用Qt Designer生成的界面文件。当构建工程时,编译器依赖Qt4的用户界面转换器UIC(UI Converter)将Qt Designer生成的UI文件转换成固定格式的C/C++头文件,这个头文件包含了一个SetupUi()和retranslateUi()方法,分别用于生成GUI界面和设置界面语言,工程中的其他文件,只要把这个头文件包含进来,冰球低啊用SetupUi()方法,就可以使用这个UI文件。
  • 工具栏部件在源代码中直接创建,之后添加到主窗口。定义Slicer工具栏的类继承于Qt,并且在Slicer中对这个类的功能进行改进,之后再对这个预留的部件进行修改。工具栏的名称使用Qt方法进行添加。
  • 设置界面(Setting)的创建和主菜单非常的类似,都是采用UI文件帮助完成的,Setting面板有多个区域,有界面左侧的菜单进行选择。如Module Setting用于设置模块加载与否,拓展添加等。需要注意的是,设置界面在程序创建主应用对象qSlicerApplication app(argc,argv)的过程中创建,要十分注意之原文件加载的位置。
  • 三维视图界面/切片视图/控制界面很大一部分内容也是有UI文件创建,但是在添加到Slicer之前做了部分的修改。

3.2 模块框架

所有的模块包含“Help & Acknowledgement”文本框的界面框架,用于显示模块相关信息,如模块功能、开发者、教程等。这个界面框架也是采用Qt进行创建的,创建完成之后,再根据模块类型的不同添加其他界面。主窗口只需要将这个界面框架添加就能完成所有的模块界面的集成。
界面框架在Slicer中被称为qSlicerModulePanel,它与模块分类界面的关系如下图:
引用:曾文晔_浙江工业大学

3.3 可加载模块分类界面

可加载模块界面是一种使用C++开发的模块,针对每个模块的功能,开发了特定的图形用户界面。因此所有这种模块的分类界面的创建的核心部分类似,同样是采用Qt Designer进行设计。
注释模块就是可加载模块中的代表。
需要注意的是,部分可加载模块的界面还使用了一些由CTK库中定义的窗口部件,CTK是以提供应用程序级别的DICOM支持、插件框架、专门的GUI部件为重点的生物医学图像运算库。

3.4 命令行模块分类界面

所有命令行模块的分类界面的格式都是完全统一的,qSlicerCLIModuleWidget。下图是Add Scalar Module模块的分类界面部分:
注意到,该界面也是由UI文件创建(Qt Designer),再在其中添加窗口部件实现整体界面。该界面UI文件已经包含了“parameter set”标签、下拉菜单和底部的四个按钮。
但是模块的状态显示栏和参数界面,是在其他源代码中创建完毕后添加的。
  • 模块状态显示栏用于显示图像处理状态,通过调用VTK库中的方法来实现,在工程qSlicerBaseQTCLI中的qSlicerCLIProgressBar.cxx文件中定义。
  • 参数界面取决于不同的命令行模块参数。这些命令行模块参数由模块的XML文件给出。
XML文档中内容依据界面层次不同的按树形结构排布,其中parameters标签内的数据是创建模块参数界面和功能的关键。命令行模块的其他一些信息也在XML文件中给出,例如模块界面中的help和acknowledge文本框中的文本,模块名,模块分类等信息。
 程序在编译创建命令行模块的过程中,利用到了外部组件SlicerExecutionModel,它为程序提供GenerateCLP.exe工具和库ModuleDescriptionParser。前者用来在编译过程中处理XML文件,从XML文件产生固定内容的头文件,这个头文件中的一个字符串变量包含了XML中的所有信息。后者提供了一个类,将这个字符串变量中包含的字符串分析,并且存储在这个类的对象的属性中等待调用。
===============================================================================
命令行模块分类界面框架在源文件qSlicerCLIModuleWidget.cxx中的qSlicerCLIModuleWidgetPrivate: : setupUi()函数完成创建,首先调用Ui_qSlicerCLIModuleWidget: setupUi()函数来创建一个原始的界面,这个原始界面包含了程序状态显示栏和一些按钮。
然后再通过函数addParameterGroups()将模块的所有参数界面添加到这个原始界面中去。addParameterGroups()函数通过循环,将所有参数以及参数下面的具体项目分层次的全部添加到界面。

3.5 脚本模块分类界面

嵌入到模块界面框架的Python脚本模块分类界面使用Python脚本语言开发,这也正是这类模块的名称由来。脚本模块通过调用Python封装的VTK, ITK,  Qt等库的API来实现模块的功能,界面也通过类似方法来实现创建。Python脚本模块分类界面的创建过程类似于可加载模块,其不同之处在于编写的语言有所不同。
Slicer集成Python解析器,Slicer大部分API都在Python中被封装。程序可以对脚本模块(Scripted Modules)的PY文件进行解析执行。复杂的交互模块可以完全通过Python来调用使用Pyhton封装的C++的方法来进行编写(例如:Endoscopy,Editor,SampleData,ChangeTracker等),即直接调用Qt的类来创建界面,调用VTK, ITK等实现模块的功能。以下是用Python语言编写的一个名为“Hello world”的按钮。
helloWorldButton = Qt.QPushButton("HelloWorld"); //创建按钮 赋予名称
helloWorldButton.toolTip = "Print 'HelloWorld' ";  //赋予按钮提示信息
sampleFormLayout.addWidget(helloWorldButton); //将按钮加入到界面中
helloWorldButton.connect('clicked(bool)',self.onHelloWorld Button Clicked); //按钮功能和触发方式
posted on 2021-01-05 14:12  一杯清酒邀明月  阅读(642)  评论(0编辑  收藏  举报