===== 定制界面布局 ===== XT框架中界面布局的定制通过继承UIProxy实现。 应用界面依赖于应用文档,因此应用界面的注册是通过调用XDocument提供的静态函数完成: static bool bRegisterTestUI = LOCAL_NAMESPACE::XDocument::registerUIProxy(DocumentTestID, CreateTestProxy, DestroyTestProxy); 其中DocumentTestID是注册应用文档时生成的整型ID标识,后面的两个参数分别为Proxy的构造接口和析构接口,在接口中调用具体的构造函数与析构函数(所有的界面代理均需重新实现这两个接口): bool CreateTestProxy(MainFrame* frame, XDocument * doc,UIProxy ** proxy) { TestProxy * t = new TestProxy(frame,doc); if (t == 0) { return false; } *proxy = t; return true; } void DestroyTestProxy(UIProxy * proxy) { delete static_cast(proxy); } 在界面代理的构造函数,根据应用的需要添加视图、定制窗口布局和创建对象树模型,其中对象树模型根据Qt库中QTreeView控件的MVC设计思路而来,用于向XTreeView提供数据([[class:ui:xtreeview|XTreeView]]从QTreeView继承实现,可参看相关文档): TestProxy::TestProxy(MainFrame * frame,XDocument * doc):UIProxy(frame,doc) { //创建对象树Model,按照QTreeView控件的MVC机制 m_pDocTreeMdl = new TestTreeModel(m_pDoc, m_pFrame); //添加新的视图 m_pCurrentDocView = new TestView(m_pFrame, m_pDoc); m_pDocViews->push_back(m_pCurrentDocView); //定制窗口 m_pCmdDock = new QDockWidget(QString().fromLocal8Bit("设置"), m_pFrame); m_pCmdDock->setFeatures(QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetFloatable); m_pCmdDock->setAllowedAreas(Qt::AllDockWidgetAreas); } 在启动与应用文档适配的应用界面之前,应重新实现activate函数以正确的激活对应的界面代理,在此函数中主要对界面窗口重新布局,设置该应用界面特有的属性,如程序名称、三维视图背景色等等,并恢复之前的界面状态(在多个应用来回切换的情况下), 如视图视角等等: void TestProxy::activate() { UIProxy::activate(); //设置功能对话框样式 auto cmdWnd = static_cast(m_pFrame->getCommandWindow()); cmdWnd->setStyleSheet(QString("background-color:#F8F8F8; ")); //设置程序名称 m_pFrame->setWindowTitle(QString().fromLocal8Bit("静力分析前处理")); //恢复视图视角 if (m_pDoc->getViewData()->getVisualAngle()->isValid())getRender()->loadVisualAngle(m_pDoc->getViewData()->getVisualAngle()); //设置视图背景色 XPreference::getInstance()->setVariable(_RENDER_BACKGROUND_TOP_COLOR, "216,216,255", "ui"); XPreference::getInstance()->setVariable(_RENDER_BACKGROUND_BOTTOM_COLOR, "128,128,192", "ui"); getRender()->updateColorSetting(); getRender()->refresh(); //布局子窗口 auto treeDock = m_pFrame->getDock(m_pFrame->getObjectTree()); m_pFrame->removeDockWidget(treeDock); m_pFrame->addDockWidget(Qt::LeftDockWidgetArea, treeDock); auto prpDock = m_pFrame->getDock(m_pFrame->getPropertyWnd()); m_pFrame->removeDockWidget(prpDock); m_pFrame->addDockWidget(Qt::LeftDockWidgetArea, prpDock); auto pickDock = m_pFrame->getDock(m_pFrame->getPickWnd()); m_pFrame->removeDockWidget(pickDock); m_pFrame->addDockWidget(Qt::LeftDockWidgetArea, pickDock); auto msgDock = m_pFrame->getDock(m_pFrame->getMessageWnd()); m_pFrame->removeDockWidget(msgDock); m_pFrame->addDockWidget(Qt::BottomDockWidgetArea, msgDock); m_pFrame->setCorner(Qt::BottomLeftCorner, Qt::LeftDockWidgetArea); m_pCmdDock->setWidget(cmdWnd); cmdWnd->setWndButtonVisible(Wnd_OK | Wnd_Cancel, false); m_pFrame->addDockWidget(Qt::LeftDockWidgetArea, m_pCmdDock); treeDock->showNormal(); msgDock->showNormal(); prpDock->showNormal(); pickDock->showNormal(); m_pCmdDock->showNormal(); m_pFrame->splitDockWidget(treeDock, m_pCmdDock, Qt::Horizontal); m_pFrame->splitDockWidget(treeDock, prpDock, Qt::Vertical); pickDock->hide(); } 在离开该应用界面时,也应重新实现deactivate函数以清除该应用特有的设定,如固定功能对话框变为浮动对话框等等。 void PreUIProxy::deactivate() { auto cmdWnd = static_cast(m_pFrame->getCommandWindow()); cmdWnd->setDockFixed(false); getRender()->saveVisualAngle(m_pDoc->getViewData()->getVisualAngle()); UIProxy::deactivate(); m_pFrame->removeDockWidget(m_pCmdDock); cmdWnd->setParent(m_pFrame); m_pCmdDock->setWidget(0); m_pCmdDock->hide(); } 一般的,当用户在对象树上单击某个对象时会在XPropertyWnd显示其属性,如果希望在XPropertyWnd显示一些特殊的属性时,界面代理需要重新实现listProperty接口,如果希望显示材料分配的数量,按如下代码实现即可: void TestProxy::listProperty(TypeID type,const XItem * item,TypeID domainType ) { const XItem * di = (const XItem *)item; auto doc = m_pFrame->getCurrentDocument(); XPropertyWnd * psw = m_pFrame->getPropertyWnd(); if (type == Domain_Material) { psw->clear(); psw->addItem(&SheetItem("材料数量", doc->getItemManager(Domain_Material)->getItemCount())); psw->addItem(&SheetItem("材料分配数量", doc->getItemManager(Domain_Property)->getItemCount())); } else return UIProxy::listProperty(type, item, domainType); }