最近做东西需要osg三维渲染与Qt界面结合,网上查了不少都是不完整的。自己写不出来就想到了一个比较无耻的办法,把osgQt中的GraphicsWindowQt文件下的内容粘贴出来,将class GLWidget : public QGLWidget 改为自己的类 class QWidgetViewer : public QGLWidget;
这样就能完全重写QGLwidget的各种虚函数,自己的各种事件响应都解决!!
平时都做寄生虫,今天也分享点东西给大家。
------------2019/3/8 补充 今天发现自己写的都傻死了,简直丑陋,分享个更好的(这个肯定好用):
链接:https://pan.baidu.com/s/1pHkOTtrLMwCI3xGZEV_08A 密码:v3v2
目录
QWidgetViewer.h
QWidgetViewer.cpp
这里是怎么调用:
/*********************************************
* Author:zmh
* Email :[email protected]
* DATE :2018/8/24
* File:QWidgetViewer.h
* osg嵌入到Qt 干货 改写的osgQt::GraphicsWindowQt
* 直接事件响应函数重写就可以
***********************************************/
#pragma once
#include
#include
#include
#ifndef _DEBUG
#pragma comment(lib,"osgQt.lib")
#else
#pragma comment(lib,"osgQtd.lib")
#pragma comment(lib,"osgd.lib")
#endif
class GraphicsWindowQt1;
class QWidgetViewer : public QGLWidget
{
typedef QGLWidget inherited;
public:
QWidgetViewer(QWidget* parent = NULL, const QGLWidget* shareWidget = NULL, Qt::WindowFlags f = 0, bool forwardKeyEvents = false);
QWidgetViewer(QGLContext* context, QWidget* parent = NULL, const QGLWidget* shareWidget = NULL, Qt::WindowFlags f = 0, bool forwardKeyEvents = false);
QWidgetViewer(const QGLFormat& format, QWidget* parent = NULL, const QGLWidget* shareWidget = NULL, Qt::WindowFlags f = 0, bool forwardKeyEvents = false);
virtual ~QWidgetViewer();
inline void setGraphicsWindow(GraphicsWindowQt1* gw) { _gw = gw; }
inline GraphicsWindowQt1* getGraphicsWindow() { return _gw; }
inline const GraphicsWindowQt1* getGraphicsWindow() const { return _gw; }
inline bool getForwardKeyEvents() const { return _forwardKeyEvents; }
virtual void setForwardKeyEvents(bool f) { _forwardKeyEvents = f; }
inline bool getTouchEventsEnabled() const { return _touchEventsEnabled; }
void setTouchEventsEnabled(bool e);
void setKeyboardModifiers(QInputEvent* event);
virtual void keyPressEvent(QKeyEvent* event);
virtual void keyReleaseEvent(QKeyEvent* event);
virtual void mousePressEvent(QMouseEvent* event);
virtual void mouseReleaseEvent(QMouseEvent* event);
virtual void mouseDoubleClickEvent(QMouseEvent* event);
virtual void mouseMoveEvent(QMouseEvent* event);
virtual void wheelEvent(QWheelEvent* event);
virtual bool gestureEvent(QGestureEvent* event);
protected:
int getNumDeferredEvents()
{
QMutexLocker lock(&_deferredEventQueueMutex);
return _deferredEventQueue.count();
}
void enqueueDeferredEvent(QEvent::Type eventType, QEvent::Type removeEventType = QEvent::None)
{
QMutexLocker lock(&_deferredEventQueueMutex);
if (removeEventType != QEvent::None)
{
if (_deferredEventQueue.removeOne(removeEventType))
_eventCompressor.remove(eventType);
}
if (_eventCompressor.find(eventType) == _eventCompressor.end())
{
_deferredEventQueue.enqueue(eventType);
_eventCompressor.insert(eventType);
}
}
void processDeferredEvents();
friend class GraphicsWindowQt1;
GraphicsWindowQt1* _gw;
QMutex _deferredEventQueueMutex;
QQueue _deferredEventQueue;
QSet _eventCompressor;
bool _touchEventsEnabled;
bool _forwardKeyEvents;
qreal _devicePixelRatio;
virtual void resizeEvent(QResizeEvent* event);
virtual void moveEvent(QMoveEvent* event);
virtual void glDraw();
virtual bool event(QEvent* event);
};
class GraphicsWindowQt1 : public osgViewer::GraphicsWindow
{
public:
GraphicsWindowQt1(osg::GraphicsContext::Traits* traits, QWidget* parent = NULL, const QGLWidget* shareWidget = NULL, Qt::WindowFlags f = 0);
GraphicsWindowQt1(QWidgetViewer* widget);
virtual ~GraphicsWindowQt1();
inline QWidgetViewer* getGLWidget() { return _widget; }
inline const QWidgetViewer* getGLWidget() const { return _widget; }
/// deprecated
inline QWidgetViewer* getGraphWidget() { return _widget; }
/// deprecated
inline const QWidgetViewer* getGraphWidget() const { return _widget; }
struct WindowData : public osg::Referenced
{
WindowData(QWidgetViewer* widget = NULL, QWidget* parent = NULL) : _widget(widget), _parent(parent) {}
QWidgetViewer* _widget;
QWidget* _parent;
};
bool init(QWidget* parent, const QGLWidget* shareWidget, Qt::WindowFlags f);
static QGLFormat traits2qglFormat(const osg::GraphicsContext::Traits* traits);
static void qglFormat2traits(const QGLFormat& format, osg::GraphicsContext::Traits* traits);
static osg::GraphicsContext::Traits* createTraits(const QGLWidget* widget);
virtual bool setWindowRectangleImplementation(int x, int y, int width, int height);
virtual void getWindowRectangle(int& x, int& y, int& width, int& height);
virtual bool setWindowDecorationImplementation(bool windowDecoration);
virtual bool getWindowDecoration() const;
virtual void grabFocus();
virtual void grabFocusIfPointerInWindow();
virtual void raiseWindow();
virtual void setWindowName(const std::string& name);
virtual std::string getWindowName();
virtual void useCursor(bool cursorOn);
virtual void setCursor(MouseCursor cursor);
inline bool getTouchEventsEnabled() const { return _widget->getTouchEventsEnabled(); }
virtual void setTouchEventsEnabled(bool e) { _widget->setTouchEventsEnabled(e); }
virtual bool valid() const;
virtual bool realizeImplementation();
virtual bool isRealizedImplementation() const;
virtual void closeImplementation();
virtual bool makeCurrentImplementation();
virtual bool releaseContextImplementation();
virtual void swapBuffersImplementation();
virtual void runOperations();
virtual void requestWarpPointer(float x, float y);
protected:
friend class QWidgetViewer;
QWidgetViewer* _widget;
bool _ownsWidget;
QCursor _currentCursor;
bool _realized;
};
#include "QWidgetViewer.h"
#include
#include
#include
#include
#include
#if (QT_VERSION>=QT_VERSION_CHECK(4, 6, 0))
# define USE_GESTURES
# include
# include
#endif
using namespace osgQt;
class QtKeyboardMap
{
public:
QtKeyboardMap()
{
mKeyMap[Qt::Key_Escape] = osgGA::GUIEventAdapter::KEY_Escape;
mKeyMap[Qt::Key_Delete] = osgGA::GUIEventAdapter::KEY_Delete;
mKeyMap[Qt::Key_Home] = osgGA::GUIEventAdapter::KEY_Home;
mKeyMap[Qt::Key_Enter] = osgGA::GUIEventAdapter::KEY_KP_Enter;
mKeyMap[Qt::Key_End] = osgGA::GUIEventAdapter::KEY_End;
mKeyMap[Qt::Key_Return] = osgGA::GUIEventAdapter::KEY_Return;
mKeyMap[Qt::Key_PageUp] = osgGA::GUIEventAdapter::KEY_Page_Up;
mKeyMap[Qt::Key_PageDown] = osgGA::GUIEventAdapter::KEY_Page_Down;
mKeyMap[Qt::Key_Left] = osgGA::GUIEventAdapter::KEY_Left;
mKeyMap[Qt::Key_Right] = osgGA::GUIEventAdapter::KEY_Right;
mKeyMap[Qt::Key_Up] = osgGA::GUIEventAdapter::KEY_Up;
mKeyMap[Qt::Key_Down] = osgGA::GUIEventAdapter::KEY_Down;
mKeyMap[Qt::Key_Backspace] = osgGA::GUIEventAdapter::KEY_BackSpace;
mKeyMap[Qt::Key_Tab] = osgGA::GUIEventAdapter::KEY_Tab;
mKeyMap[Qt::Key_Space] = osgGA::GUIEventAdapter::KEY_Space;
mKeyMap[Qt::Key_Delete] = osgGA::GUIEventAdapter::KEY_Delete;
mKeyMap[Qt::Key_Alt] = osgGA::GUIEventAdapter::KEY_Alt_L;
mKeyMap[Qt::Key_Shift] = osgGA::GUIEventAdapter::KEY_Shift_L;
mKeyMap[Qt::Key_Control] = osgGA::GUIEventAdapter::KEY_Control_L;
mKeyMap[Qt::Key_Meta] = osgGA::GUIEventAdapter::KEY_Meta_L;
mKeyMap[Qt::Key_F1] = osgGA::GUIEventAdapter::KEY_F1;
mKeyMap[Qt::Key_F2] = osgGA::GUIEventAdapter::KEY_F2;
mKeyMap[Qt::Key_F3] = osgGA::GUIEventAdapter::KEY_F3;
mKeyMap[Qt::Key_F4] = osgGA::GUIEventAdapter::KEY_F4;
mKeyMap[Qt::Key_F5] = osgGA::GUIEventAdapter::KEY_F5;
mKeyMap[Qt::Key_F6] = osgGA::GUIEventAdapter::KEY_F6;
mKeyMap[Qt::Key_F7] = osgGA::GUIEventAdapter::KEY_F7;
mKeyMap[Qt::Key_F8] = osgGA::GUIEventAdapter::KEY_F8;
mKeyMap[Qt::Key_F9] = osgGA::GUIEventAdapter::KEY_F9;
mKeyMap[Qt::Key_F10] = osgGA::GUIEventAdapter::KEY_F10;
mKeyMap[Qt::Key_F11] = osgGA::GUIEventAdapter::KEY_F11;
mKeyMap[Qt::Key_F12] = osgGA::GUIEventAdapter::KEY_F12;
mKeyMap[Qt::Key_F13] = osgGA::GUIEventAdapter::KEY_F13;
mKeyMap[Qt::Key_F14] = osgGA::GUIEventAdapter::KEY_F14;
mKeyMap[Qt::Key_F15] = osgGA::GUIEventAdapter::KEY_F15;
mKeyMap[Qt::Key_F16] = osgGA::GUIEventAdapter::KEY_F16;
mKeyMap[Qt::Key_F17] = osgGA::GUIEventAdapter::KEY_F17;
mKeyMap[Qt::Key_F18] = osgGA::GUIEventAdapter::KEY_F18;
mKeyMap[Qt::Key_F19] = osgGA::GUIEventAdapter::KEY_F19;
mKeyMap[Qt::Key_F20] = osgGA::GUIEventAdapter::KEY_F20;
mKeyMap[Qt::Key_hyphen] = '-';
mKeyMap[Qt::Key_Equal] = '=';
mKeyMap[Qt::Key_division] = osgGA::GUIEventAdapter::KEY_KP_Divide;
mKeyMap[Qt::Key_multiply] = osgGA::GUIEventAdapter::KEY_KP_Multiply;
mKeyMap[Qt::Key_Minus] = '-';
mKeyMap[Qt::Key_Plus] = '+';
//mKeyMap[Qt::Key_H ] = osgGA::GUIEventAdapter::KEY_KP_Home;
//mKeyMap[Qt::Key_ ] = osgGA::GUIEventAdapter::KEY_KP_Up;
//mKeyMap[92 ] = osgGA::GUIEventAdapter::KEY_KP_Page_Up;
//mKeyMap[86 ] = osgGA::GUIEventAdapter::KEY_KP_Left;
//mKeyMap[87 ] = osgGA::GUIEventAdapter::KEY_KP_Begin;
//mKeyMap[88 ] = osgGA::GUIEventAdapter::KEY_KP_Right;
//mKeyMap[83 ] = osgGA::GUIEventAdapter::KEY_KP_End;
//mKeyMap[84 ] = osgGA::GUIEventAdapter::KEY_KP_Down;
//mKeyMap[85 ] = osgGA::GUIEventAdapter::KEY_KP_Page_Down;
mKeyMap[Qt::Key_Insert] = osgGA::GUIEventAdapter::KEY_KP_Insert;
//mKeyMap[Qt::Key_Delete ] = osgGA::GUIEventAdapter::KEY_KP_Delete;
}
~QtKeyboardMap()
{
}
int remapKey(QKeyEvent* event)
{
KeyMap::iterator itr = mKeyMap.find(event->key());
if (itr == mKeyMap.end())
{
return int(*(event->text().toLatin1().data()));
}
else
return itr->second;
}
private:
typedef std::map KeyMap;
KeyMap mKeyMap;
};
static QtKeyboardMap s_QtKeyboardMap;
#if (QT_VERSION < QT_VERSION_CHECK(5, 2, 0))
#define GETDEVICEPIXELRATIO() 1.0
#else
#define GETDEVICEPIXELRATIO() devicePixelRatio()
#endif
QWidgetViewer::QWidgetViewer(QWidget* parent, const QGLWidget* shareWidget, Qt::WindowFlags f, bool forwardKeyEvents)
: QGLWidget(parent, shareWidget, f),
_gw(NULL),
_touchEventsEnabled(false),
_forwardKeyEvents(forwardKeyEvents)
{
_devicePixelRatio = GETDEVICEPIXELRATIO();
}
QWidgetViewer::QWidgetViewer(QGLContext* context, QWidget* parent, const QGLWidget* shareWidget, Qt::WindowFlags f,
bool forwardKeyEvents)
: QGLWidget(context, parent, shareWidget, f),
_gw(NULL),
_touchEventsEnabled(false),
_forwardKeyEvents(forwardKeyEvents)
{
_devicePixelRatio = GETDEVICEPIXELRATIO();
}
QWidgetViewer::QWidgetViewer(const QGLFormat& format, QWidget* parent, const QGLWidget* shareWidget, Qt::WindowFlags f,
bool forwardKeyEvents)
: QGLWidget(format, parent, shareWidget, f),
_gw(NULL),
_touchEventsEnabled(false),
_forwardKeyEvents(forwardKeyEvents)
{
_devicePixelRatio = GETDEVICEPIXELRATIO();
}
QWidgetViewer::~QWidgetViewer()
{
// close GraphicsWindowQt1 and remove the reference to us
if (_gw)
{
_gw->close();
_gw->_widget = NULL;
_gw = NULL;
}
}
void QWidgetViewer::setTouchEventsEnabled(bool e)
{
#ifdef USE_GESTURES
if (e == _touchEventsEnabled)
return;
_touchEventsEnabled = e;
if (_touchEventsEnabled)
{
grabGesture(Qt::PinchGesture);
}
else
{
ungrabGesture(Qt::PinchGesture);
}
#endif
}
void QWidgetViewer::processDeferredEvents()
{
QQueue deferredEventQueueCopy;
{
QMutexLocker lock(&_deferredEventQueueMutex);
deferredEventQueueCopy = _deferredEventQueue;
_eventCompressor.clear();
_deferredEventQueue.clear();
}
while (!deferredEventQueueCopy.isEmpty())
{
QEvent event(deferredEventQueueCopy.dequeue());
QGLWidget::event(&event);
}
}
bool QWidgetViewer::event(QEvent* event)
{
#ifdef USE_GESTURES
if (event->type() == QEvent::Gesture)
return gestureEvent(static_cast(event));
#endif
// QEvent::Hide
//
// workaround "Qt-workaround" that does glFinish before hiding the widget
// (the Qt workaround was seen at least in Qt 4.6.3 and 4.7.0)
//
// Qt makes the context current, performs glFinish, and releases the context.
// This makes the problem in OSG multithreaded environment as the context
// is active in another thread, thus it can not be made current for the purpose
// of glFinish in this thread.
// QEvent::ParentChange
//
// Reparenting QWidgetViewer may create a new underlying window and a new GL context.
// Qt will then call doneCurrent on the GL context about to be deleted. The thread
// where old GL context was current has no longer current context to render to and
// we cannot make new GL context current in this thread.
// We workaround above problems by deferring execution of problematic event requests.
// These events has to be enqueue and executed later in a main GUI thread (GUI operations
// outside the main thread are not allowed) just before makeCurrent is called from the
// right thread. The good place for doing that is right after swap in a swapBuffersImplementation.
if (event->type() == QEvent::Hide)
{
// enqueue only the last of QEvent::Hide and QEvent::Show
enqueueDeferredEvent(QEvent::Hide, QEvent::Show);
return true;
}
else if (event->type() == QEvent::Show)
{
// enqueue only the last of QEvent::Show or QEvent::Hide
enqueueDeferredEvent(QEvent::Show, QEvent::Hide);
return true;
}
else if (event->type() == QEvent::ParentChange)
{
// enqueue only the last QEvent::ParentChange
enqueueDeferredEvent(QEvent::ParentChange);
return true;
}
// perform regular event handling
return QGLWidget::event(event);
}
void QWidgetViewer::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;
_gw->getEventQueue()->getCurrentEventState()->setModKeyMask(mask);
}
void QWidgetViewer::resizeEvent(QResizeEvent* event)
{
const QSize& size = event->size();
int scaled_width = static_cast(size.width()*_devicePixelRatio);
int scaled_height = static_cast(size.height()*_devicePixelRatio);
_gw->resized(x(), y(), scaled_width, scaled_height);
_gw->getEventQueue()->windowResize(x(), y(), scaled_width, scaled_height);
_gw->requestRedraw();
}
void QWidgetViewer::moveEvent(QMoveEvent* event)
{
//写上自己的事件处理
#if 1
const QPoint& pos = event->pos();
int scaled_width = static_cast(width()*_devicePixelRatio);
int scaled_height = static_cast(height()*_devicePixelRatio);
_gw->resized(pos.x(), pos.y(), scaled_width, scaled_height);
_gw->getEventQueue()->windowResize(pos.x(), pos.y(), scaled_width, scaled_height);
#endif
}
void QWidgetViewer::glDraw()
{
_gw->requestRedraw();
}
void QWidgetViewer::keyPressEvent(QKeyEvent* event)
{
//写上自己的事件处理
#if 1
setKeyboardModifiers(event);
int value = s_QtKeyboardMap.remapKey(event);
_gw->getEventQueue()->keyPress(value);
// this passes the event to the regular Qt key event processing,
// among others, it closes popup windows on ESC and forwards the event to the parent widgets
if (_forwardKeyEvents)
inherited::keyPressEvent(event);
#endif
}
void QWidgetViewer::keyReleaseEvent(QKeyEvent* event)
{
//写上自己的事件处理
#if 1
if (event->isAutoRepeat())
{
event->ignore();
}
else
{
setKeyboardModifiers(event);
int value = s_QtKeyboardMap.remapKey(event);
_gw->getEventQueue()->keyRelease(value);
}
// this passes the event to the regular Qt key event processing,
// among others, it closes popup windows on ESC and forwards the event to the parent widgets
if (_forwardKeyEvents)
inherited::keyReleaseEvent(event);
#endif
}
void QWidgetViewer::mousePressEvent(QMouseEvent* event)
{
//写上自己的事件处理
#if 1
int button = 0;
switch (event->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;
}
setKeyboardModifiers(event);
_gw->getEventQueue()->mouseButtonPress(event->x()*_devicePixelRatio, event->y()*_devicePixelRatio, button);
#endif
}
void QWidgetViewer::mouseReleaseEvent(QMouseEvent* event)
{
//写上自己的事件处理
#if 1
int button = 0;
switch (event->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;
}
setKeyboardModifiers(event);
_gw->getEventQueue()->mouseButtonRelease(event->x()*_devicePixelRatio, event->y()*_devicePixelRatio, button);
#endif
}
void QWidgetViewer::mouseDoubleClickEvent(QMouseEvent* event)
{
//写上自己的事件处理
#if 1
int button = 0;
switch (event->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;
}
setKeyboardModifiers(event);
_gw->getEventQueue()->mouseDoubleButtonPress(event->x()*_devicePixelRatio, event->y()*_devicePixelRatio, button);
#endif
}
void QWidgetViewer::mouseMoveEvent(QMouseEvent* event)
{
//写上自己的事件处理
#if 1
setKeyboardModifiers(event);
_gw->getEventQueue()->mouseMotion(event->x()*_devicePixelRatio, event->y()*_devicePixelRatio);
#endif
}
void QWidgetViewer::wheelEvent(QWheelEvent* event)
{
//写上自己的事件处理
#if 1
setKeyboardModifiers(event);
_gw->getEventQueue()->mouseScroll(
event->orientation() == Qt::Vertical ?
(event->delta() > 0 ? osgGA::GUIEventAdapter::SCROLL_UP : osgGA::GUIEventAdapter::SCROLL_DOWN) :
(event->delta() > 0 ? osgGA::GUIEventAdapter::SCROLL_LEFT : osgGA::GUIEventAdapter::SCROLL_RIGHT));
#endif
}
#ifdef USE_GESTURES
static osgGA::GUIEventAdapter::TouchPhase translateQtGestureState(Qt::GestureState state)
{
osgGA::GUIEventAdapter::TouchPhase touchPhase;
switch (state)
{
case Qt::GestureStarted:
touchPhase = osgGA::GUIEventAdapter::TOUCH_BEGAN;
break;
case Qt::GestureUpdated:
touchPhase = osgGA::GUIEventAdapter::TOUCH_MOVED;
break;
case Qt::GestureFinished:
case Qt::GestureCanceled:
touchPhase = osgGA::GUIEventAdapter::TOUCH_ENDED;
break;
default:
touchPhase = osgGA::GUIEventAdapter::TOUCH_UNKNOWN;
};
return touchPhase;
}
#endif
bool QWidgetViewer::gestureEvent(QGestureEvent* qevent)
{
#ifndef USE_GESTURES
return false;
#else
bool accept = false;
if (QPinchGesture* pinch = static_cast(qevent->gesture(Qt::PinchGesture)))
{
const QPointF qcenterf = pinch->centerPoint();
const float angle = pinch->totalRotationAngle();
const float scale = pinch->totalScaleFactor();
const QPoint pinchCenterQt = mapFromGlobal(qcenterf.toPoint());
const osg::Vec2 pinchCenter(pinchCenterQt.x(), pinchCenterQt.y());
//We don't have absolute positions of the two touches, only a scale and rotation
//Hence we create pseudo-coordinates which are reasonable, and centered around the
//real position
const float radius = (width() + height()) / 4;
const osg::Vec2 vector(scale*cos(angle)*radius, scale*sin(angle)*radius);
const osg::Vec2 p0 = pinchCenter + vector;
const osg::Vec2 p1 = pinchCenter - vector;
osg::ref_ptr event = 0;
const osgGA::GUIEventAdapter::TouchPhase touchPhase = translateQtGestureState(pinch->state());
if (touchPhase == osgGA::GUIEventAdapter::TOUCH_BEGAN)
{
event = _gw->getEventQueue()->touchBegan(0, touchPhase, p0[0], p0[1]);
}
else if (touchPhase == osgGA::GUIEventAdapter::TOUCH_MOVED)
{
event = _gw->getEventQueue()->touchMoved(0, touchPhase, p0[0], p0[1]);
}
else
{
event = _gw->getEventQueue()->touchEnded(0, touchPhase, p0[0], p0[1], 1);
}
if (event)
{
event->addTouchPoint(1, touchPhase, p1[0], p1[1]);
accept = true;
}
}
if (accept)
qevent->accept();
return accept;
#endif
}
GraphicsWindowQt1::GraphicsWindowQt1(osg::GraphicsContext::Traits* traits, QWidget* parent, const QGLWidget* shareWidget, Qt::WindowFlags f)
: _realized(false)
{
_widget = NULL;
_traits = traits;
init(parent, shareWidget, f);
}
GraphicsWindowQt1::GraphicsWindowQt1(QWidgetViewer* widget)
: _realized(false)
{
_widget = widget;
_traits = _widget ? createTraits(_widget) : new osg::GraphicsContext::Traits;
init(NULL, NULL, 0);
}
GraphicsWindowQt1::~GraphicsWindowQt1()
{
close();
// remove reference from QWidgetViewer
if (_widget)
_widget->_gw = NULL;
}
bool GraphicsWindowQt1::init(QWidget* parent, const QGLWidget* shareWidget, Qt::WindowFlags f)
{
// update _widget and parent by WindowData
WindowData* windowData = _traits.get() ? dynamic_cast(_traits->inheritedWindowData.get()) : 0;
if (!_widget)
_widget = windowData ? windowData->_widget : NULL;
if (!parent)
parent = windowData ? windowData->_parent : NULL;
// create widget if it does not exist
_ownsWidget = _widget == NULL;
if (!_widget)
{
// shareWidget
if (!shareWidget) {
GraphicsWindowQt1* sharedContextQt = dynamic_cast(_traits->sharedContext.get());
if (sharedContextQt)
shareWidget = sharedContextQt->getGLWidget();
}
// WindowFlags
Qt::WindowFlags flags = f | Qt::Window | Qt::CustomizeWindowHint;
_traits->windowDecoration = false;
if (_traits->windowDecoration)
flags |= Qt::WindowTitleHint | Qt::WindowMinMaxButtonsHint | Qt::WindowSystemMenuHint
#if (QT_VERSION_CHECK(4, 5, 0) <= QT_VERSION)
| Qt::WindowCloseButtonHint
#endif
;
// create widget
_widget = new QWidgetViewer(traits2qglFormat(_traits.get()), parent, shareWidget, flags);
}
// set widget name and position
// (do not set it when we inherited the widget)
if (_ownsWidget)
{
_widget->setWindowTitle(_traits->windowName.c_str());
_widget->move(_traits->x, _traits->y);
if (!_traits->supportsResize) _widget->setFixedSize(_traits->width, _traits->height);
else _widget->resize(_traits->width, _traits->height);
}
// initialize widget properties
_widget->setAutoBufferSwap(false);
_widget->setMouseTracking(true);
_widget->setFocusPolicy(Qt::WheelFocus);
_widget->setGraphicsWindow(this);
useCursor(_traits->useCursor);
// initialize State
setState(new osg::State);
getState()->setGraphicsContext(this);
// initialize contextID
if (_traits.valid() && _traits->sharedContext.valid())
{
getState()->setContextID(_traits->sharedContext->getState()->getContextID());
incrementContextIDUsageCount(getState()->getContextID());
}
else
{
getState()->setContextID(osg::GraphicsContext::createNewContextID());
}
// make sure the event queue has the correct window rectangle size and input range
getEventQueue()->syncWindowRectangleWithGraphicsContext();
return true;
}
QGLFormat GraphicsWindowQt1::traits2qglFormat(const osg::GraphicsContext::Traits* traits)
{
QGLFormat format(QGLFormat::defaultFormat());
format.setAlphaBufferSize(traits->alpha);
format.setRedBufferSize(traits->red);
format.setGreenBufferSize(traits->green);
format.setBlueBufferSize(traits->blue);
format.setDepthBufferSize(traits->depth);
format.setStencilBufferSize(traits->stencil);
format.setSampleBuffers(traits->sampleBuffers);
format.setSamples(traits->samples);
format.setAlpha(traits->alpha > 0);
format.setDepth(traits->depth > 0);
format.setStencil(traits->stencil > 0);
format.setDoubleBuffer(traits->doubleBuffer);
format.setSwapInterval(traits->vsync ? 1 : 0);
format.setStereo(traits->quadBufferStereo ? 1 : 0);
return format;
}
void GraphicsWindowQt1::qglFormat2traits(const QGLFormat& format, osg::GraphicsContext::Traits* traits)
{
traits->red = format.redBufferSize();
traits->green = format.greenBufferSize();
traits->blue = format.blueBufferSize();
traits->alpha = format.alpha() ? format.alphaBufferSize() : 0;
traits->depth = format.depth() ? format.depthBufferSize() : 0;
traits->stencil = format.stencil() ? format.stencilBufferSize() : 0;
traits->sampleBuffers = format.sampleBuffers() ? 1 : 0;
traits->samples = format.samples();
traits->quadBufferStereo = format.stereo();
traits->doubleBuffer = format.doubleBuffer();
traits->vsync = format.swapInterval() >= 1;
}
osg::GraphicsContext::Traits* GraphicsWindowQt1::createTraits(const QGLWidget* widget)
{
osg::GraphicsContext::Traits *traits = new osg::GraphicsContext::Traits;
qglFormat2traits(widget->format(), traits);
QRect r = widget->geometry();
traits->x = r.x();
traits->y = r.y();
traits->width = r.width();
traits->height = r.height();
traits->windowName = widget->windowTitle().toLocal8Bit().data();
Qt::WindowFlags f = widget->windowFlags();
traits->windowDecoration = (f & Qt::WindowTitleHint) &&
(f & Qt::WindowMinMaxButtonsHint) &&
(f & Qt::WindowSystemMenuHint);
QSizePolicy sp = widget->sizePolicy();
traits->supportsResize = sp.horizontalPolicy() != QSizePolicy::Fixed ||
sp.verticalPolicy() != QSizePolicy::Fixed;
return traits;
}
bool GraphicsWindowQt1::setWindowRectangleImplementation(int x, int y, int width, int height)
{
if (_widget == NULL)
return false;
_widget->setGeometry(x, y, width, height);
return true;
}
void GraphicsWindowQt1::getWindowRectangle(int& x, int& y, int& width, int& height)
{
if (_widget)
{
const QRect& geom = _widget->geometry();
x = geom.x();
y = geom.y();
width = geom.width();
height = geom.height();
}
}
bool GraphicsWindowQt1::setWindowDecorationImplementation(bool windowDecoration)
{
Qt::WindowFlags flags = Qt::Window | Qt::CustomizeWindowHint; //|Qt::WindowStaysOnTopHint;
if(windowDecoration)
flags |= Qt::WindowTitleHint | Qt::WindowMinMaxButtonsHint | Qt::WindowSystemMenuHint;
_traits->windowDecoration = windowDecoration;
if (_widget)
{
_widget->setWindowFlags(flags);
return true;
}
return false;
}
bool GraphicsWindowQt1::getWindowDecoration() const
{
return _traits->windowDecoration;
}
void GraphicsWindowQt1::grabFocus()
{
if (_widget)
_widget->setFocus(Qt::ActiveWindowFocusReason);
}
void GraphicsWindowQt1::grabFocusIfPointerInWindow()
{
if (_widget->underMouse())
_widget->setFocus(Qt::ActiveWindowFocusReason);
}
void GraphicsWindowQt1::raiseWindow()
{
if (_widget)
_widget->raise();
}
void GraphicsWindowQt1::setWindowName(const std::string& name)
{
if (_widget)
_widget->setWindowTitle(name.c_str());
}
std::string GraphicsWindowQt1::getWindowName()
{
return _widget ? _widget->windowTitle().toStdString() : "";
}
void GraphicsWindowQt1::useCursor(bool cursorOn)
{
if (_widget)
{
_traits->useCursor = cursorOn;
if (!cursorOn) _widget->setCursor(Qt::BlankCursor);
else _widget->setCursor(_currentCursor);
}
}
void GraphicsWindowQt1::setCursor(MouseCursor cursor)
{
if (cursor == InheritCursor && _widget)
{
_widget->unsetCursor();
}
switch (cursor)
{
case NoCursor: _currentCursor = Qt::BlankCursor; break;
case RightArrowCursor: case LeftArrowCursor: _currentCursor = Qt::ArrowCursor; break;
case InfoCursor: _currentCursor = Qt::SizeAllCursor; break;
case DestroyCursor: _currentCursor = Qt::ForbiddenCursor; break;
case HelpCursor: _currentCursor = Qt::WhatsThisCursor; break;
case CycleCursor: _currentCursor = Qt::ForbiddenCursor; break;
case SprayCursor: _currentCursor = Qt::SizeAllCursor; break;
case WaitCursor: _currentCursor = Qt::WaitCursor; break;
case TextCursor: _currentCursor = Qt::IBeamCursor; break;
case CrosshairCursor: _currentCursor = Qt::CrossCursor; break;
case HandCursor: _currentCursor = Qt::OpenHandCursor; break;
case UpDownCursor: _currentCursor = Qt::SizeVerCursor; break;
case LeftRightCursor: _currentCursor = Qt::SizeHorCursor; break;
case TopSideCursor: case BottomSideCursor: _currentCursor = Qt::UpArrowCursor; break;
case LeftSideCursor: case RightSideCursor: _currentCursor = Qt::SizeHorCursor; break;
case TopLeftCorner: _currentCursor = Qt::SizeBDiagCursor; break;
case TopRightCorner: _currentCursor = Qt::SizeFDiagCursor; break;
case BottomRightCorner: _currentCursor = Qt::SizeBDiagCursor; break;
case BottomLeftCorner: _currentCursor = Qt::SizeFDiagCursor; break;
default: break;
};
if (_widget) _widget->setCursor(_currentCursor);
}
bool GraphicsWindowQt1::valid() const
{
return _widget && _widget->isValid();
}
bool GraphicsWindowQt1::realizeImplementation()
{
// save the current context
// note: this will save only Qt-based contexts
const QGLContext *savedContext = QGLContext::currentContext();
// initialize GL context for the widget
if (!valid())
_widget->glInit();
// make current
_realized = true;
bool result = makeCurrent();
_realized = false;
// fail if we do not have current context
if (!result)
{
if (savedContext)
const_cast(savedContext)->makeCurrent();
OSG_WARN << "Window realize: Can make context current." << std::endl;
return false;
}
_realized = true;
// make sure the event queue has the correct window rectangle size and input range
getEventQueue()->syncWindowRectangleWithGraphicsContext();
// make this window's context not current
// note: this must be done as we will probably make the context current from another thread
// and it is not allowed to have one context current in two threads
if (!releaseContext())
OSG_WARN << "Window realize: Can not release context." << std::endl;
// restore previous context
if (savedContext)
const_cast(savedContext)->makeCurrent();
return true;
}
bool GraphicsWindowQt1::isRealizedImplementation() const
{
return _realized;
}
void GraphicsWindowQt1::closeImplementation()
{
if (_widget)
_widget->close();
_realized = false;
}
void GraphicsWindowQt1::runOperations()
{
// While in graphics thread this is last chance to do something useful before
// graphics thread will execute its operations.
if (_widget->getNumDeferredEvents() > 0)
_widget->processDeferredEvents();
if (QGLContext::currentContext() != _widget->context())
_widget->makeCurrent();
GraphicsWindow::runOperations();
}
bool GraphicsWindowQt1::makeCurrentImplementation()
{
if (_widget->getNumDeferredEvents() > 0)
_widget->processDeferredEvents();
_widget->makeCurrent();
return true;
}
bool GraphicsWindowQt1::releaseContextImplementation()
{
_widget->doneCurrent();
return true;
}
void GraphicsWindowQt1::swapBuffersImplementation()
{
_widget->swapBuffers();
// FIXME: the processDeferredEvents should really be executed in a GUI (main) thread context but
// I couln't find any reliable way to do this. For now, lets hope non of *GUI thread only operations* will
// be executed in a QGLWidget::event handler. On the other hand, calling GUI only operations in the
// QGLWidget event handler is an indication of a Qt bug.
if (_widget->getNumDeferredEvents() > 0)
_widget->processDeferredEvents();
// We need to call makeCurrent here to restore our previously current context
// which may be changed by the processDeferredEvents function.
if (QGLContext::currentContext() != _widget->context())
_widget->makeCurrent();
}
void GraphicsWindowQt1::requestWarpPointer(float x, float y)
{
if (_widget)
QCursor::setPos(_widget->mapToGlobal(QPoint((int)x, (int)y)));
}
main.cpp
#include
#include "osgInQt.h"
#include
#include
#include "QWidgetViewer.h"
#pragma comment(lib,"osgGAd.lib")
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
osgQt::initQtWindowingSystem(); //其实是调用了静态的 windowingSystemInterface 操作系统窗口接口
osg::Group* sceneroot = new osg::Group;
sceneroot->addChild(osgDB::readNodeFile("cow.osg"));
osg::ref_ptr viewer = new osgViewer::Viewer;
viewer->addEventHandler(new osgGA::StateSetManipulator(viewer->getCamera()->getOrCreateStateSet()));
viewer->addEventHandler(new osgViewer::StatsHandler);
viewer->setThreadingModel(osgViewer::ViewerBase::SingleThreaded);
viewer->setSceneData(sceneroot);
viewer->setCameraManipulator(new osgGA::TrackballManipulator);
osgQt::setViewer(viewer.get());
QWidgetViewer* glw = new QWidgetViewer();
GraphicsWindowQt1* graphicswin = new GraphicsWindowQt1(glw);
graphicswin->setCursor(GraphicsWindowQt1::MouseCursor::HandCursor); //设置鼠标
viewer->getCamera()->setViewport(new osg::Viewport(0, 0, glw->width(), glw->height()));
viewer->getCamera()->setGraphicsContext(graphicswin);
glw->setWindowTitle(QString::fromLocal8Bit("osg嵌入qt成功了"));
glw->show();
return a.exec();
}
这里还有个硬货:https://blog.csdn.net/u010292461/article/details/52768030(这个最好)
如果之前看到这篇博文,就不用费力整了。
示例资源下载:https://download.csdn.net/download/a_treasure/10634028(代码和这里的一模一样,只不过是个.sln)