我正在尝试集成 Qt5 和 OpenSceneGraph。我发现了这个最小的嵌入示例。
当我将示例中定义的小部件封装到 QDockWidget 中并向示例中添加一个简单的文本标签时,当我取消停靠容器窗口时,文本消失了。当我重新停靠窗口时,不再显示文本。
我已经在 OpenSceneGraph 论坛上问过这个问题,但没有成功。我的猜测是它与 GL 相关的方法和小部件的内部重新设置有关。
在我的示例中,只有构造函数和主函数是从原始函数中修改的。
这是我修改后的示例(main.cpp):
#include<QApplication>
#include<QMainWindow>
#include<QOpenGLWidget>
#include<QMouseEvent>
#include<QWheelEvent>
#include<QDesktopWidget>
#include<QScreen>
#include<QtGlobal>
#include<QWindow>
#include<QWidget>
#include<QDockWidget>
#include<QVBoxLayout>
#include<osg/ref_ptr>
#include<osgViewer/GraphicsWindow>
#include<osgText/Text>
#include<osgViewer/Viewer>
#include<osg/Camera>
#include<osg/ShapeDrawable>
#include<osg/StateSet>
#include<osg/Material>
#include<osgGA/EventQueue>
#include<osgGA/TrackballManipulator>
#include <iostream>
#include <stdio.h>
class QtOSGWidget : public QOpenGLWidget
{
public:
QtOSGWidget(qreal scaleX, qreal scaleY, QWidget* parent = 0)
: QOpenGLWidget(parent)
, _mGraphicsWindow(new osgViewer::GraphicsWindowEmbedded( this->x(), this->y(),
this->width(), this->height() ) )
, _mViewer(new osgViewer::Viewer)
, m_scaleX(scaleX)
, m_scaleY(scaleY)
{
osg::Cylinder* cylinder = new osg::Cylinder( osg::Vec3( 0.f, 0.f, 0.f ), 0.25f, 0.5f );
osg::ShapeDrawable* sd = new osg::ShapeDrawable( cylinder );
sd->setColor( osg::Vec4( 0.8f, 0.5f, 0.2f, 1.f ) );
osg::Geode* geode = new osg::Geode;
geode->addDrawable(sd);
// adding text to the visualization
osgText::Text * test = new osgText::Text();
test->setDataVariance(osg::Object::DYNAMIC);
test->setCharacterSize(1.0);
test->setColor(osg::Vec4(0.0, 0.0, 0.0, 1.0));
test->setAlignment(osgText::Text::CENTER_BOTTOM);
test->setAxisAlignment(osgText::TextBase::SCREEN);
test->setCharacterSizeMode(osgText::Text::OBJECT_COORDS);
test->setText("CYLINDER");
geode->addDrawable(test);
// end adding text
osg::Camera* camera = new osg::Camera;
camera->setViewport( 0, 0, this->width(), this->height() );
camera->setClearColor( osg::Vec4( 0.9f, 0.9f, 1.f, 1.f ) );
float aspectRatio = static_cast<float>( this->width()) / static_cast<float>( this->height() );
camera->setProjectionMatrixAsPerspective( 30.f, aspectRatio, 1.f, 1000.f );
camera->setGraphicsContext( _mGraphicsWindow );
_mViewer->setCamera(camera);
_mViewer->setSceneData(geode);
osgGA::TrackballManipulator* manipulator = new osgGA::TrackballManipulator;
manipulator->setAllowThrow( false );
this->setMouseTracking(true);
_mViewer->setCameraManipulator(manipulator);
_mViewer->setThreadingModel(osgViewer::Viewer::SingleThreaded);
// _mViewer->realize();
}
virtual ~QtOSGWidget(){}
void setScale(qreal X, qreal Y)
{
m_scaleX = X;
m_scaleY = Y;
this->resizeGL(this->width(), this->height());
}
protected:
virtual void paintGL()
{
_mViewer->frame();
}
virtual void resizeGL( int width, int height )
{
this->getEventQueue()->windowResize(this->x()*m_scaleX, this->y() * m_scaleY, width*m_scaleX, height*m_scaleY);
_mGraphicsWindow->resized(this->x()*m_scaleX, this->y() * m_scaleY, width*m_scaleX, height*m_scaleY);
osg::Camera* camera = _mViewer->getCamera();
camera->setViewport(0, 0, this->width()*m_scaleX, this->height()* m_scaleY);
}
virtual void initializeGL()
{
osg::Geode* geode = dynamic_cast<osg::Geode*>(_mViewer->getSceneData());
osg::StateSet* stateSet = geode->getOrCreateStateSet();
osg::Material* material = new osg::Material;
material->setColorMode( osg::Material::AMBIENT_AND_DIFFUSE );
stateSet->setAttributeAndModes( material, osg::StateAttribute::ON );
stateSet->setMode( GL_DEPTH_TEST, osg::StateAttribute::ON );
}
virtual void mouseMoveEvent(QMouseEvent* event)
{
this->getEventQueue()->mouseMotion(event->x()*m_scaleX, event->y()*m_scaleY);
}
virtual void mousePressEvent(QMouseEvent* event)
{
unsigned int button = 0;
switch (event->button())
{
case Qt::LeftButton:
button = 1;
break;
case Qt::MiddleButton:
button = 2;
break;
case Qt::RightButton:
button = 3;
break;
default:
break;
}
this->getEventQueue()->mouseButtonPress(event->x()*m_scaleX, event->y()*m_scaleY, button);
}
virtual void mouseReleaseEvent(QMouseEvent* event)
{
unsigned int button = 0;
switch (event->button())
{
case Qt::LeftButton:
button = 1;
break;
case Qt::MiddleButton:
button = 2;
break;
case Qt::RightButton:
button = 3;
break;
default:
break;
}
this->getEventQueue()->mouseButtonRelease(event->x()*m_scaleX, event->y()*m_scaleY, button);
}
virtual void wheelEvent(QWheelEvent* event)
{
int delta = event->delta();
osgGA::GUIEventAdapter::ScrollingMotion motion = delta > 0 ?
osgGA::GUIEventAdapter::SCROLL_UP : osgGA::GUIEventAdapter::SCROLL_DOWN;
this->getEventQueue()->mouseScroll(motion);
}
virtual bool event(QEvent* event)
{
bool handled = QOpenGLWidget::event(event);
this->update();
return handled;
}
private:
osgGA::EventQueue* getEventQueue() const
{
osgGA::EventQueue* eventQueue = _mGraphicsWindow->getEventQueue();
return eventQueue;
}
osg::ref_ptr<osgViewer::GraphicsWindowEmbedded> _mGraphicsWindow;
osg::ref_ptr<osgViewer::Viewer> _mViewer;
qreal m_scaleX, m_scaleY;
};
int main(int argc, char** argv)
{
// This was necessary for keeping the context when undocking
// without it nothing is shown on the widget when gets undocked
QApplication::setAttribute(Qt::AA_ShareOpenGLContexts);
QApplication qapp(argc, argv);
QMainWindow window;
// Here starts code to put the QtOSGWidget inside a dock area
QDockWidget * visDock = new QDockWidget(&window);
visDock->setFloating(false);
visDock->setFeatures(QDockWidget::DockWidgetFloatable | QDockWidget::DockWidgetMovable);
visDock->setAllowedAreas(Qt::TopDockWidgetArea);
QWidget * dockWidgetContent = new QWidget();
QVBoxLayout * verticalLayout = new QVBoxLayout(dockWidgetContent);
verticalLayout->setSpacing(6);
verticalLayout->setContentsMargins(11, 11, 11, 11);
QWidget * containerWidget = new QWidget(dockWidgetContent);
QHBoxLayout * horizontalLayout = new QHBoxLayout(containerWidget);
horizontalLayout->setSpacing(0);
horizontalLayout->setContentsMargins(11, 11, 11, 11);
horizontalLayout->setContentsMargins(0, 0, 0, 0);
QtOSGWidget* widget = new QtOSGWidget(1, 1, containerWidget);
horizontalLayout->addWidget(widget);
verticalLayout->addWidget(containerWidget);
visDock->setWidget(dockWidgetContent);
window.addDockWidget(static_cast<Qt::DockWidgetArea>(4), visDock);
// No central widget is used for the example
window.setCentralWidget(Q_NULLPTR);
window.show();
return qapp.exec();
}