将OSG嵌入QT窗口系统中,实现拖拽界面

一、原理

OSG底层使用的是OpenGL图形系统,QT也增加了对OpenGL的支持,因此,可以通过QT的OpenGL模块,实现将OSG窗口嵌入到QT中,这样可以充分利用QT的UI界面设计,满足OSG的2D的界面系统的不足。当然除了使用OSG做2D渲染特效,可以尽情享受QT界面设计带来的方便。


二、准备

1. QT对OpenGL的支持:

QT中,场景视图模型模块,可以使用OpenGL绘制基本图元。视图,即:QGraphicsView ,场景,即:QGraphicsScene,当然还有基本图元项,QGraphicsItem,这里暂不介绍。
简单设计思路:我们新建一个QT MainWindow项目。首先,将场景,加入到视图中,接着,将视图加入MainWindow中,这样以后,我们就可以使用MainWindow在视图中浏览场景,场景包含OSG内容,这样,我们就达到了目的。

2. OSG窗口移植:

OSG的窗口API中,可以嵌入各种各样的窗口系统,这给我移植到QT带来的可能,在OSG参考文档中,我选择使用GraphicsWindowEmbedded 来创建可移植的窗口。

三、QT 模型视图框架

QT环境:

qt-opensource-windows-x86-msvc2010_opengl-5.4.1.exe
qt-vs-addin-1.2.4-opensource.exe

设计:

视图类QGraphicsView

GLView.h
GLView.cpp

文件:GLView.h

#pragma once
#include <QtWidgets/QGraphicsView>
#include <QtOpenGL/QGLWidget>
#include <QtGui/QResizeEvent>#include "GLScene.h"class GLView : public QGraphicsView
{
public:GLView(QWidget *parent = 0);~GLView(void);protected://更新视图的时候,更新场景void resizeEvent(QResizeEvent *event);public:QGLWidget *m_widget;GLScene *m_scene;
};

文件:GLView.cpp

#include "GLView.h"#include <QtWidgets/QMessageBox>GLView::GLView(QWidget *parent):QGraphicsView(parent),m_widget(new QGLWidget(QGLFormat(QGL::DoubleBuffer))),m_scene(new GLScene(this))
{this->resize(800,600);//设置视口大小this->setViewport(m_widget);//将m_widget设置为视口:为了使用OpenGL渲染,你要设置一个新的QGLWidget作为QGraphicsView的视口m_widget->setMouseTracking(true);//鼠标追踪this->viewport()->setMinimumSize(1,1);this->setScene(m_scene);this->setMinimumSize(1,1); //设置视图的最小尺寸this->scene()->setSceneRect(0,0,this->width(),this->height());//设置场景大小this->setViewportUpdateMode(QGraphicsView::FullViewportUpdate);//设置视图的更新方式:整个视图更新
}GLView::~GLView(void)
{
}//更新视图的时候,更新场景
void GLView::resizeEvent( QResizeEvent *event )
{//更新场景大小m_scene->setSceneRect(this->rect().left(),this->rect().right(),this->rect().width(),this->rect().height());m_scene->resizeViewer();}

场景类QGraphicsScene

文件:GLScene.h

#pragma once
#include <QtWidgets/QGraphicsScene>
#include <QtWidgets/qgraphicsscene.h>
#include <QtWidgets/QGraphicsSceneEvent>
#include <QTimerEvent>
#include <QtGui//QPainter>#include "OsgLib.h"
#include <osgViewer/Viewer>
#include <osgDB/ReadFile>
#include <osgGA/TrackballManipulator>
#include <osgViewer/ViewerEventHandlers>#include "KeyBoardMap.h"static KeyBoardMap s_QtKeyboardMap;//按键映射class GLScene :public QGraphicsScene
{
public:GLScene(QObject *parent = 0);~GLScene(void);protected://绘制场景void drawBackground(QPainter *painter, const QRectF &rect);//窗口更新函数:使用定时器,定时更新void timerEvent(QTimerEvent *);protected://鼠标事件void mousePressEvent(QGraphicsSceneMouseEvent * mouseEvent);void mouseReleaseEvent(QGraphicsSceneMouseEvent * mouseEvent);void mouseMoveEvent(QGraphicsSceneMouseEvent * mouseEvent);void mouseDoubleClickEvent(QGraphicsSceneMouseEvent * mouseEvent);void wheelEvent(QGraphicsSceneWheelEvent * wheelEvent);//键盘按键void keyPressEvent(QKeyEvent * keyEvent);void keyReleaseEvent(QKeyEvent * keyEvent);int   timer_id;public://更新OSG窗口void resizeViewer();void setKeyboardModifiers( QInputEvent* event );//组合键
public:osg::ref_ptr<osgViewer::Viewer> m_viewer;
};

文件:GLScene.cpp

#include "GLScene.h"GLScene::GLScene(QObject *parent):
QGraphicsScene(parent),m_viewer(NULL),timer_id(0)
{//OSG初始化m_viewer = new osgViewer::Viewer;m_viewer->setUpViewerAsEmbeddedInWindow(0,0,800,600);//设置窗口的嵌入大小m_viewer->setSceneData(osgDB::readNodeFile("glider.osg"));m_viewer->setCameraManipulator(new osgGA::TrackballManipulator);//添加操作器m_viewer->addEventHandler(new osgViewer::StatsHandler);//状态信息m_viewer->realize();//实例化GraphicsContexttimer_id = startTimer(0);//当定时器触发时,应用程序会发送一个QTimerEvent,如果参数为0,那么定时器事件每次发生时没有窗口系统事件处理。
}GLScene::~GLScene(void)
{
}//绘制场景
void GLScene::drawBackground( QPainter *painter, const QRectF &rect )
{painter->beginNativePainting();painter->setRenderHint(QPainter::Antialiasing);//抗锯齿m_viewer->frame();//m_viewer->getViewerBase()->frame();painter->endNativePainting();}//窗口更新函数
void GLScene::timerEvent(QTimerEvent *)
{this->update();
}void GLScene::mousePressEvent( QGraphicsSceneMouseEvent * mouseEvent )
{//std::cout<<"mousePressEvent"<<std::endl;QGraphicsScene::mousePressEvent(mouseEvent);int button = 0;switch ( mouseEvent->button() ){case Qt::LeftButton: button = 1; break;case Qt::MidButton: button = 2; break;case Qt::RightButton: button = 3; break;case Qt::NoButton: button = 0; break;default: button = 0; break;}//_gw->getEventQueue()->mouseButtonRelease( event->x(), event->y(), button );(dynamic_cast<osgViewer::GraphicsWindow*> (m_viewer->getCamera()->getGraphicsContext()))->getEventQueue()->mouseButtonPress( mouseEvent->scenePos().x(), mouseEvent->scenePos().y(), button );
}void GLScene::mouseReleaseEvent( QGraphicsSceneMouseEvent * mouseEvent )
{//std::cout<<"mouseReleaseEvent"<<std::endl;QGraphicsScene::mouseReleaseEvent(mouseEvent);int button = 0;switch ( mouseEvent->button() ){case Qt::LeftButton: button = 1; break;case Qt::MidButton: button = 2; break;case Qt::RightButton: button = 3; break;case Qt::NoButton: button = 0; break;default: button = 0; break;}(dynamic_cast<osgViewer::GraphicsWindow*> (m_viewer->getCamera()->getGraphicsContext()))->getEventQueue()->mouseButtonRelease( mouseEvent->scenePos().x(), mouseEvent->scenePos().y(), button );}void GLScene::mouseMoveEvent( QGraphicsSceneMouseEvent * mouseEvent )
{//std::cout<<"mouseMoveEvent"<<std::endl;QGraphicsScene::mouseMoveEvent(mouseEvent);(dynamic_cast<osgViewer::GraphicsWindow*> (m_viewer->getCamera()->getGraphicsContext()))->getEventQueue()->mouseMotion( mouseEvent->scenePos().x(), mouseEvent->scenePos().y());
}void GLScene::mouseDoubleClickEvent( QGraphicsSceneMouseEvent * mouseEvent )
{//std::cout<<"mouseDoubleClickEvent"<<std::endl;QGraphicsScene::mouseDoubleClickEvent(mouseEvent);int button = 0;switch ( mouseEvent->button() ){case Qt::LeftButton: button = 1; break;case Qt::MidButton: button = 2; break;case Qt::RightButton: button = 3; break;case Qt::NoButton: button = 0; break;default: button = 0; break;}(dynamic_cast<osgViewer::GraphicsWindow*> (m_viewer->getCamera()->getGraphicsContext()))->getEventQueue()->mouseDoubleButtonPress( mouseEvent->scenePos().x(), mouseEvent->scenePos().y(), button );
}void GLScene::wheelEvent( QGraphicsSceneWheelEvent * wheelEvent )
{//std::cout<<"wheelEvent"<<std::endl;QGraphicsScene::wheelEvent(wheelEvent);(dynamic_cast<osgViewer::GraphicsWindow*> (m_viewer->getCamera()->getGraphicsContext()))->getEventQueue()->mouseScroll(wheelEvent->orientation() == Qt::Vertical ?(wheelEvent->delta()>0 ? osgGA::GUIEventAdapter::SCROLL_UP : osgGA::GUIEventAdapter::SCROLL_DOWN) :(wheelEvent->delta()>0 ? osgGA::GUIEventAdapter::SCROLL_LEFT : osgGA::GUIEventAdapter::SCROLL_RIGHT) );}void GLScene::keyPressEvent( QKeyEvent * keyEvent )
{setKeyboardModifiers(keyEvent);int value = s_QtKeyboardMap.remapKey( keyEvent );(dynamic_cast<osgViewer::GraphicsWindow*> (m_viewer->getCamera()->getGraphicsContext()))->getEventQueue()->keyPress( value );QGraphicsScene::keyPressEvent(keyEvent);
}void GLScene::keyReleaseEvent( QKeyEvent * keyEvent )
{//std::cout<<"keyReleaseEvent"<<std::endl;QGraphicsScene::keyReleaseEvent(keyEvent);int value = s_QtKeyboardMap.remapKey( keyEvent );(dynamic_cast<osgViewer::GraphicsWindow*> (m_viewer->getCamera()->getGraphicsContext()))->getEventQueue()->keyRelease( value );QGraphicsScene::keyPressEvent(keyEvent);
}//OSG场景窗口更新
void GLScene::resizeViewer()
{//更新OSG窗口大小(dynamic_cast<osgViewer::GraphicsWindow*> (m_viewer->getCamera()->getGraphicsContext()))->resized(this->sceneRect().x(),this->sceneRect().y(),this->sceneRect().width(),this->sceneRect().height());(dynamic_cast<osgViewer::GraphicsWindow*> (m_viewer->getCamera()->getGraphicsContext()))->getEventQueue()->windowResize(this->sceneRect().x(),this->sceneRect().y(),this->sceneRect().width(),this->sceneRect().height());//?  更新状态S按键(dynamic_cast<osgViewer::GraphicsWindow*> (m_viewer->getCamera()->getGraphicsContext()))->requestRedraw();//?}//组合键
void GLScene::setKeyboardModifiers( QInputEvent* event )
{int modkey = event->modifiers() & (Qt::ShiftModifier | Qt::ControlModifier | Qt::AltModifier);unsigned int mask = 0;if ( modkey & Qt::ShiftModifier ) mask |= osgGA::GUIEventAdapter::MODKEY_SHIFT;if ( modkey & Qt::ControlModifier ) mask |= osgGA::GUIEventAdapter::MODKEY_CTRL;if ( modkey & Qt::AltModifier ) mask |= osgGA::GUIEventAdapter::MODKEY_ALT;(dynamic_cast<osgViewer::GraphicsWindow*> (m_viewer->getCamera()->getGraphicsContext()))->getEventQueue()->getCurrentEventState()->setModKeyMask( mask );
}

QMainWindow类

文件:qtosgmainwindow.h

#ifndef QTOSGMAINWINDOW_H
#define QTOSGMAINWINDOW_H#include <QtWidgets/QMainWindow>
#include "ui_qtosgmainwindow.h"#include "GLView.h"class QtOsgMainWindow : public QMainWindow
{Q_OBJECTpublic:QtOsgMainWindow(QWidget *parent = 0);~QtOsgMainWindow();protected://更新视图void resizeEvent(QResizeEvent *);private:Ui::QtOsgMainWindowClass ui;GLView *m_glview;
};#endif // QTOSGMAINWINDOW_H

文件:qtosgmainwindow.cpp

#include "qtosgmainwindow.h"QtOsgMainWindow::QtOsgMainWindow(QWidget *parent): QMainWindow(parent)
{ui.setupUi(this);this->resize(800,600);//MainWindow设置窗口大小this->setCorner(Qt::BottomLeftCorner,Qt::LeftDockWidgetArea);this->setCorner(Qt::BottomRightCorner,Qt::RightDockWidgetArea);this->setCorner(Qt::TopLeftCorner,Qt::LeftDockWidgetArea);this->setCorner(Qt::TopRightCorner,Qt::RightDockWidgetArea);ui.gridLayout->setMargin(-1);m_glview = new GLView(this);//隐藏滚动条m_glview->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);m_glview->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);this->layout()->addWidget(m_glview);
}QtOsgMainWindow::~QtOsgMainWindow()
{}void QtOsgMainWindow::resizeEvent( QResizeEvent * )
{std::cout<<"MainWindow resizeEvent."<<std::endl;m_glview->resize(this->rect().width(),this->rect().height());//更新视图
}

注:文件使用KeyBoardMap.h等文件,注释掉即可,该文件用于QT按键与OSG按键的映射.

五、Main函数

#include "qtosgmainwindow.h"
#include <QtWidgets/QApplication>int main(int argc, char *argv[])
{QApplication a(argc, argv);QtOsgMainWindow w;w.show();return a.exec();
}

到此,可实现QT窗口的,OSG显示.

将OSG嵌入QT窗口系统中,实现拖拽界面相关推荐

  1. 深度探索QT窗口系统——几何篇

    深度探索QT窗口系统--几何篇 窗口作为界面编程中最重要的部分,没有窗口就没有界面,是窗口让我们摆脱了DOS时代,按钮是一个窗口,文本框是一个窗口,标签页是一个窗口.一个窗口可以由多个窗口组成,每天我 ...

  2. 深度探索Qt窗口系统——布局篇

    深度探索Qt窗口系统--布局篇 虽然界面管理器可以完成窗口布局,但是对于动态布局的情况下,这种做法就无能为力了,现实中界面经常要支持国际化,对于同一内容用不同语言翻译可能长度不一,这就需要窗口动态布局 ...

  3. Qt之QAbstractItemView视图项拖拽(二)

    一.需求说明 上一篇文章Qt之QAbstractItemView视图项拖拽(一)讲述了实现QAbstractItemView视图项拖拽的一种方式,是基于QDrag实现的,这个类是qt自己封装好了的,所 ...

  4. .net中实现拖拽控件

    在.net中实现拖拽控件主要用到以下函数: MouseDown(object sender, MouseEventArgs e) MouseUp(object sender, MouseEventAr ...

  5. vue中实现拖拽排序

    原生拖拽 API 实现拖拽 设置元素 dragable 将元素的 dragable 属性设置 为 true (文本 图片 链接 的draggable 属性默认为 true)则元素可拖放 <div ...

  6. 中如何使用echart_jQueryEasyUI中的拖拽事件如何使用

    jQueryEasyUI中的拖拽事件通过给它设置代理元素使其拖拽.可设置拖动元素相对于x.y轴拖动,可设置拖拽何时停止等效果 jQuery中的easyui是一个非常好用的插件,它虽然使用简单方便,但是 ...

  7. java swing 控件拖动_java swing中实现拖拽功能示例

    java实现拖拽示例 Swing中实现拖拽功能,代码很简单,都有注释,自己看,运行效果如下图: package com; import java.awt.*;import java.awt.datat ...

  8. eclipse插件开发:自定义导航器中的拖拽定义

    有时候需要对导航器中的拖拽对象进行赋值,使用的场景是,拖拽导航器中的某个文件或者类或方法等,到某个编辑器中,, 因为默认的导航器所配备的拖拽动作,或则不能满足我们的需要,所有,有必要自定义,,拖拽器, ...

  9. selenium中录制拖拽动作

    今天工作中遇到了selenium中录制拖拽动作需求:在同一个页面上,将一个table中的元素拖拽到另外一个table中. 通过查看帮助文档是使用dragAndDrop或类似的命令.根据使用方法drag ...

最新文章

  1. 搭建WSS 开发测试环境
  2. 压缩感知 的自我理解
  3. python生成的exe程序在其他电脑打开报错_9102年你还不会搭建Python环境
  4. JS判断上传文件类型
  5. ConcurrentHashMap的源码分析-fullAddCount源码分析
  6. LeetCode 257. 二叉树的所有路径 思考分析
  7. crt 8.7.3 黑暗模式_民谣缠绕厄运金属,抒情中的黑暗故事
  8. mysql order by random,sql-MySQL:ORDER BY RAND()的替代方法
  9. wireshark 抓包分析 TCPIP协议的握手
  10. OSPF OVER FR HUB-SPPKE
  11. 基于linux在线预览
  12. 计算机科学与技术_基于Java web的计算机图书借阅管理系统的设计与实现.docx
  13. iptables高性能前端优化-无压力配置1w+条规则
  14. word怎么恢复保存前的文件,word文件恢复
  15. qq飞车显示服务器维护中,QQ飞车手游更新出现异常怎么办?更新异常原因及解决方法技巧...
  16. 网站服务器配置在哪里设置,web服务器配置参数 web服务器建立网站具体步骤
  17. Java日志框架 -- 日志框架介绍、日志门面技术、JUL日志(JUL架构、JUL入门示例、JUL日志级别、JUL日志的配置文件)
  18. 山东大学项目实训小组一——基于深度学习的AI视频剪辑器“易剪”
  19. caff2 与 pytorch 模型的转换--onnx
  20. CAD-VB多段线、波浪线、射线、构造线

热门文章

  1. 10款性能测试工具供参考
  2. 网站建设-通过链接策略建立排名:
  3. js 数组转json和json转数组
  4. 作为软件开发人员,如何简单的推销自己
  5. linux 复制除某个文件夹外所有的文件
  6. 记录一下uni-app输入框input的@input事件失效问题
  7. 【企业】把握蘑菇管理原理,合理培养人才
  8. 【电力系统】基于多元宇宙算法求解电力系统多目标优化问题附Matlab代码
  9. 解除root无法远程登录的限制
  10. 如何恢复手机误删除照片