OsgEarth QT开发新手遇到多屏问题

用QT弄了一个窗口,窗口下有2个子窗口,一个用来QGis来做二维显示,一个用OsgEarth来做三维显示,但今天在调的时候,QGIS的2维没有问题,但OsgEarth的三维只要一运行就会出现多屏问题。

3维子窗口按照预想没有问题,但莫名多了2个全屏独立子窗口(自己的电脑是双屏),和3维子窗口显示的一样,用Spy++抓了一下竟也是同一窗口。

猜想可能是QT的问题,因为用 osgEarth::QtGui::ViewerWidget(m_Viewer); New出来的窗口设有设置窗口属性,而且后来是设置其为主窗口的子窗口的。

但看了Qt中QWidget的setParent的使用方法一文,心里就知道错了。

原文说的很明白:
setParent是有两个接口的,一个是setParent(QWidget parent),一个是setParent(QWidget parent, Qt::WindowFlags f),其中如果调用第一个参数的话,parent会重新设置窗口的标志位,如果希望保持原来的窗口标志位,则必须要指定一个参数。举一个简单的例子,如果你原来的窗口的标志位是Qt::Window|Qt::FramelesssWindowHint(一个自由窗体,不带边框),那么你需要将这个参数带到flags中,如果不指定的话,则会将其窗口属性修改为QWidget了(会跟父窗口合并,并且会将窗口的位置移动到(0,0)的位置。

没办法,怎么办呢?只有试了,自己基本上把所有的代码都注释了,发现问题依旧.

但现在的问题定位到应该是osgEarth的问题了,估计是从Duilib改成MFC造成的问题,但怎么改,自己也不清楚,因为自己也刚开始看QT,啥也不会。

回归冷静,找到OsgEarth官方给的例子,osgearth_qt_simple和osgearth_qt_windows来看,对照的代码来看,查找差异。
在osgearth_qt_windows中有,人家的代码是这样的:

void addView()
    {
        // the new View we want to add:
        osgViewer::View* view = new osgViewer::View();

        // a widget to hold our view:
        QWidget* viewWidget = new osgEarth::QtGui::ViewWidget(view);

        // a dialog to hold the view widget:
        QDialog* win = new QDialog(this);
        win->setModal( false );
        win->setLayout( new QHBoxLayout() );
        win->layout()->addWidget( viewWidget );
        int x = osgEarth::Random().next( 1024 );
        int y = osgEarth::Random().next( 768 );
        win->setGeometry( x, y, 640, 480 );
        win->show();

        // set up the view
        view->setCameraManipulator( new osgEarth::Util::EarthManipulator );
        view->setSceneData( _scene.get() );  
        view->getDatabasePager()->setUnrefImageDataAfterApplyPolicy(true,false);

        // add it to the composite viewer.
        _viewer.addView( view );
    }

人家用的是默认的Camera,自己就自己的Camera和操作器的也屏蔽掉,问题依旧。

后来细细再细看一些代码,发现自己调用了一句话:
这个函数好熟悉,百度了一下,粗略地看了一下王锐的最长的一帧,感觉 好像就是它了,屏蔽掉,问题解决。

后来细看了一下这篇文章,这也是我去年年底分析的源代码,只是函数名没记住,搞了大半年的Windows驱动,大半年没用OsgEarth,忘光光了…

下来分析一下可能的原因吧:为什么说是可能了,是因为要需要原代码的,细细分析。

realize这个函数其实就是在进行帧循环前的一个操作,其功能就是根据用户的设置来创建GraphicsContext,也就是Camera等。

由于自己是在Qt的Widget构造前( new osgEarth::QtGui::ViewerWidget(m_Viewer)调用,所以宿主窗口尚未建立,OsgEarth可能会默认的图形上下文,由于自己电脑里有2个屏蔽,也就加2个,后来指定了一个窗口Widget,所以就是三个相同的Camera,只是投影窗口一样。

后来为了验证自己猜想的,自己把realize放到 osgEarth::QtGui::ViewerWidget之后,依旧OK,和猜想的一致。

联想到我们有进在开发Windows的时候,比如要显示一个MessageBox,其所属窗口会填NULL,而NULL是以桌窗窗口为窗主窗口的。
我想OsgEarth可能会内容去枚举图形显示设备,如果没有指定显示窗口,会将桌面增加进去吧,而后面自己再用Viewer创建的Widget后加入的,因为没有删除以前的,所以才会出现多屏的。

写了这么多,只为说明一个问题,经验有时的不足,会可能把别人强调的经验会忽略掉。

也许 这是为了对自己以前读最长的一帧当时的迷迷糊糊加一点清醒济吧,也行有天自己会重新去分析osgEarth的源代码吧,希望不再仅仅是C++编程技巧上的收获,更是思想上的