單窗口多視口實現思路

  眾多工程應用軟件中,一個模型中查看的數據會多種多樣,比如:三維模型視圖,受力圖表等。然后,在查看過程中,用戶可能還需要同時對各種數據進行對比查看等。在以前的軟件中,多視口的實現通過多選項卡(多窗口)模式來實現的,如下圖,這在軟件操作過程中給用戶帶來了極大的不變,對于多模型來說,更是痛苦至極。

單窗口多視口實現思路的圖1

目前多視口的界面大體如下:

單窗口多視口實現思路的圖2

其中,左上為工程的整體三維視圖,右上為計算域三維網格,左下為切片、矢量圖等后處理結果,右下為部分邊界網格。

這僅是列舉的一小部分,這對于用戶來說,查看不同的數據,對比分析也更加直觀。而卻各個視口獨立于其他視口,只與當前的工程有關。用戶可以在不同的視口中做不同的操作,不影響其他視口。

 

實現思路:

多視口中,每個視口都“貼”在一個父窗口上。當視口被分割成兩個視口時,首先創建一個父窗口,用來“裝”原視口和新創建出來的視口,然后再將創建的父窗口“貼”于原視口的位置。流程如下表示:

單窗口多視口實現思路的圖3

實現流程:

通過上述流程,不難發現,這與數據結構中的二叉樹的數據結構類似,因此,采用動態數組來描述多視口數據。父窗口采用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[location];

cell.direction = direction;

cell.splitFraction = fraction;

 

    m_Cells.resize(2 * location + 2 + 1);

 

int child_location = (2 * location + 1);

ViewCell& child = m_Cells[child_location];

   child.view = cell.view;

cell.view = NULL;// 默認為空,在創建窗口函數中自動創建

 

    m_Cells[location] = cell;

return child_location;

}

 

4. 創建窗口:

當二叉樹的數據完成后,接下來就需要創建窗口,刷新等操作了。可以按照二叉樹的前序遍歷進行迭代了。偽代碼如下:

QWidget* createWidget(int index, QWidget* parentWdg)

{

    Direction direction = m_Cells[index].direction;

    QWidget* widget = m_Cells[index].view;

    switch (direction)

    {

    case NONE:

    {

        if (!widget)

        {

            widget = new QWidget(this);

        }

        frame->setParent(parentWdg);

        m_Cells[index].view = widget;

 

        return widget;

    }

    case VERTICAL:

    case HORIZONTAL:

    {

        QSplitter* splitter = qobject_cast<QSplitter*>(widget);

        if (!splitter)

        {

            splitter = new QSplitter(parentWdg);

        }

 

        m_Cells[index].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;

}

 

到此,多視口的大體實現已經完成。

登錄后免費查看全文
立即登錄
App下載
技術鄰APP
工程師必備
  • 項目客服
  • 培訓客服
  • 平臺客服

TOP