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

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

将OSG嵌入QT窗口系统中,实现拖拽界面_第1张图片

一、原理

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

将OSG嵌入QT窗口系统中,实现拖拽界面_第2张图片
二、准备

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

设计:

将OSG嵌入QT窗口系统中,实现拖拽界面_第3张图片

视图类QGraphicsView

GLView.h
GLView.cpp

文件:GLView.h

#pragma once
#include 
#include 
#include 

#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 

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 
#include 
#include 
#include 
#include 

#include "OsgLib.h"
#include 
#include 
#include 
#include 

#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 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"<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 (m_viewer->getCamera()->getGraphicsContext()))->getEventQueue()->mouseButtonPress( mouseEvent->scenePos().x(), mouseEvent->scenePos().y(), button );
}

void GLScene::mouseReleaseEvent( QGraphicsSceneMouseEvent * mouseEvent )
{
	//std::cout<<"mouseReleaseEvent"<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 (m_viewer->getCamera()->getGraphicsContext()))->getEventQueue()->mouseButtonRelease( mouseEvent->scenePos().x(), mouseEvent->scenePos().y(), button );
	
}



void GLScene::mouseMoveEvent( QGraphicsSceneMouseEvent * mouseEvent )
{
	//std::cout<<"mouseMoveEvent"< (m_viewer->getCamera()->getGraphicsContext()))->getEventQueue()->mouseMotion( mouseEvent->scenePos().x(), mouseEvent->scenePos().y());
}

void GLScene::mouseDoubleClickEvent( QGraphicsSceneMouseEvent * mouseEvent )
{
	//std::cout<<"mouseDoubleClickEvent"<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 (m_viewer->getCamera()->getGraphicsContext()))->getEventQueue()->mouseDoubleButtonPress( mouseEvent->scenePos().x(), mouseEvent->scenePos().y(), button );
}

void GLScene::wheelEvent( QGraphicsSceneWheelEvent * wheelEvent )
{
	//std::cout<<"wheelEvent"< (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 (m_viewer->getCamera()->getGraphicsContext()))->getEventQueue()->keyPress( value );
	QGraphicsScene::keyPressEvent(keyEvent);
}

void GLScene::keyReleaseEvent( QKeyEvent * keyEvent )
{
	//std::cout<<"keyReleaseEvent"< (m_viewer->getCamera()->getGraphicsContext()))->getEventQueue()->keyRelease( value );
	QGraphicsScene::keyPressEvent(keyEvent);
}

//OSG场景窗口更新
void GLScene::resizeViewer()
{
	//更新OSG窗口大小
	(dynamic_cast (m_viewer->getCamera()->getGraphicsContext()))->resized(this->sceneRect().x(),this->sceneRect().y(),this->sceneRect().width(),this->sceneRect().height());
	(dynamic_cast (m_viewer->getCamera()->getGraphicsContext()))->getEventQueue()->windowResize(this->sceneRect().x(),this->sceneRect().y(),this->sceneRect().width(),this->sceneRect().height());//?  更新状态S按键

	(dynamic_cast (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 (m_viewer->getCamera()->getGraphicsContext()))->getEventQueue()->getCurrentEventState()->setModKeyMask( mask );
}

QMainWindow类

文件:qtosgmainwindow.h

#ifndef QTOSGMAINWINDOW_H
#define QTOSGMAINWINDOW_H

#include 
#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."<resize(this->rect().width(),this->rect().height());//更新视图
}
注:文件使用KeyBoardMap.h等文件,注释掉即可,该文件用于QT按键与OSG按键的映射.

五、Main函数

#include "qtosgmainwindow.h"
#include 

int main(int argc, char *argv[])
{
	QApplication a(argc, argv);
	QtOsgMainWindow w;
	
	w.show();
	return a.exec();
}

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







你可能感兴趣的:(OpenGL,QT)