天洑软件 发表于 2019-2-19 16:14:52

单窗口多视口实现思路

本帖最后由 天洑软件 于 2019-3-27 17:57 编辑

在众多工程应用软件中,一个模型中查看的数据会多种多样,比如:三维模型视图,受力图表等。然后,在查看过程中,用户可能还需要同时对各种数据进行对比查看等。在以前的软件中,多视口的实现通过多选项卡(多窗口)模式来实现的,如下图,这在软件操作过程中给用户带来了极大的不变,对于多模型来说,更是痛苦至极。
http://www.njtf.cn/ueditor/net/upload/2017-09-18/5743c8f7-fb0e-4164-a26c-1ed34dfa66bf.png
目前多视口的界面大体如下:
http://www.njtf.cn/ueditor/net/upload/2017-09-18/bf6b8b05-5c82-40e5-8710-3a9e751e6928.png
其中,左上为工程的整体三维视图,右上为计算域三维网格,左下为切片、矢量图等后处理结果,右下为部分边界网格。这仅是列举的一小部分,这对于用户来说,查看不同的数据,对比分析也更加直观。而却各个视口独立于其他视口,只与当前的工程有关。用户可以在不同的视口中做不同的操作,不影响其他视口。 实现思路:多视口中,每个视口都“贴”在一个父窗口上。当视口被分割成两个视口时,首先创建一个父窗口,用来“装”原视口和新创建出来的视口,然后再将创建的父窗口“贴”于原视口的位置。流程如下表示:http://www.njtf.cn/ueditor/net/upload/2017-09-18/81ebba53-27ac-45c1-bd88-197f47f14cd7.png

实现流程:通过上述流程,不难发现,这与数据结构中的二叉树的数据结构类似,因此,采用动态数组来描述多视口数据。父窗口采用Qt中的QSplitter类,视口为相应的窗口类。1. 定义数据元素类型:struct ViewCell    {      Direction direction;    // 方向      double splitFraction;   // 分割比例      QWidget* view;       ViewCell() : direction(NONE), splitFraction(0.5), view(0){}};其中,direction和splitFraction当为父窗口时有效。 2. 定义数据结构QVector<ViewCell> m_Cells; 3. 分割算法:由于二叉树的特性,每分割一次,数组的变为 (2*location)+2+1个,原视口变为 2*location+1,其中,location为当前窗口的序号(序号按照二叉树的前序序号排列)。然后将location位置的元素类型更改为父窗口内容,将2*location+1位置的元素类型更改为原视口内容,伪代码如下:int split(int location, Direction direction, double fraction){ViewCell cell = m_Cells;cell.direction = direction;cell.splitFraction = fraction;     m_Cells.resize(2 * location + 2 + 1); int child_location = (2 * location + 1);ViewCell& child = m_Cells;   child.view = cell.view;cell.view = NULL;// 默认为空,在创建窗口函数中自动创建     m_Cells = cell;return child_location;} 4. 创建窗口:当二叉树的数据完成后,接下来就需要创建窗口,刷新等操作了。可以按照二叉树的前序遍历进行迭代了。伪代码如下:QWidget* createWidget(int index, QWidget* parentWdg){    Direction direction = m_Cells.direction;    QWidget* widget = m_Cells.view;    switch (direction)    {    case NONE:    {      if (!widget)      {            widget = new QWidget(this);      }      frame->setParent(parentWdg);      m_Cells.view = widget;       return widget;    }    case VERTICAL:    case HORIZONTAL:    {      QSplitter* splitter = qobject_cast<QSplitter*>(widget);      if (!splitter)      {            splitter = new QSplitter(parentWdg);      }       m_Cells.view = splitter;      splitter->setParent(parentWdg);      splitter->setOrientation(direction);// 采用前序遍历,迭代      splitter->insertWidget(0, createWidget(2 * index + 1, splitter));      splitter->insertWidget(1, createWidget(2 * index + 2, splitter));      return splitter;    }    }     return NULL;} 到此,多视口的大体实现已经完成。

关注公众号“天洑CAE技术源”了解更多相关资讯
http://forum.simwe.com/data/attachment/forum/201903/27/170148yd0wexhz999j9xd0.jpg
页: [1]
查看完整版本: 单窗口多视口实现思路