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

4 篇文章 2 订阅

将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();//实例化GraphicsContext

	timer_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_OBJECT

public:
	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显示.







  • 6
    点赞
  • 36
    收藏
    觉得还不错? 一键收藏
  • 9
    评论
要将OSG模型嵌入Qt窗口,可以使用Qt的OpenGL模块和OSGQt插件。具体步骤如下: 1. 创建一个Qt窗口,继承自QOpenGLWidget。 2. 在窗口的初始化函数,创建一个OSG Viewer对象,并将其设置为OpenGL上下文。 3. 在窗口的paintGL()函数,调用OSG的渲染函数进行渲染。 4. 在窗口的resizeGL()函数,更新OSG Viewer的视口大小。 5. 在Qt的主函数,加载OSGQt插件,以便在Qt应用程序使用OSG。 下面是一个简单的示例代码: ```cpp #include <osgViewer/Viewer> #include <osgQt/GraphicsWindowQt> class OSGWidget : public QOpenGLWidget { public: OSGWidget(QWidget* parent = nullptr) : QOpenGLWidget(parent) { osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits(); traits->windowName = "OSG Widget"; traits->x = x(); traits->y = y(); traits->width = width(); traits->height = height(); traits->windowDecoration = false; traits->doubleBuffer = true; traits->sharedContext = 0; osgQt::GraphicsWindowQt* gw = new osgQt::GraphicsWindowQt(traits.get()); osg::Camera* camera = new osg::Camera; camera->setGraphicsContext(gw); camera->setViewport(new osg::Viewport(0, 0, width(), height())); setCameraManipulator(new osgGA::TrackballManipulator); viewer.setCamera(camera); viewer.setThreadingModel(osgViewer::Viewer::SingleThreaded); } protected: void paintGL() override { viewer.frame(); } void resizeGL(int w, int h) override { viewer.getCamera()->setViewport(new osg::Viewport(0, 0, w, h)); } private: osgViewer::Viewer viewer; }; int main(int argc, char** argv) { QApplication app(argc, argv); osgDB::Registry::instance()->loadLibrary("osgdb_qt.so"); OSGWidget widget; widget.resize(640, 480); widget.show(); return app.exec(); } ``` 这里假设OSG已经正确安装,并且Qt应用程序已经配置好了OpenGL环境。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值