将Qt集成到预先编写的应用程序/框架中 [英] Integrate Qt into prewritten Application/Framework

查看:140
本文介绍了将Qt集成到预先编写的应用程序/框架中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个用c ++编写的小型可视化框架,并希望使用Qt拥有适当的GUI并控制我的可视化与之交互.目前,我正在使用GLUT创建一个窗口并在其中绘制视图.因此,我要做的就是初始化Visualization类的对象,该对象为我完成所有工作:保存模型和视图.视图本身拥有一个控制器来处理用户输入并操纵模型.我的主循环看起来像这样:

I have a small visualization framework written in c++ and want to use Qt to have a proper GUI and control over my visualizations to interact with them. currently, I am using GLUT to create a window and draw a view in it. so everything I do is initialize an object of the class Visualization which does everything for me: holding model and views. the view itself holds a controller to process user input and manipulate the model. my main loop looks like this:

Visualization* vis = new Visualization();
vis->createModel("some_file.txt");
vis->createView("unknown");

// ...

void demo_app::display()
{
  // clear the framebuffer
  glClearColor(0.3, 0.3, 0.3, 1.0);
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

  vis.update(); // looks for dirty scenes to update
  vis.render(); // draws all views which are stored in vis

  glutSwapBuffers();
}

使用GLUT,我有一个窗口,可以在其中安排多个视图.当我命令在主循环中绘制视图时,我可以执行glCommands,一切都很好.

with GLUT I have a single window in which I arrange multiple views. when I order the view to draw during the main loop I can execute glCommands and everything is fine.

所以现在我的问题是我想在多个窗口(QDialogs + QGLWidgets)中使用Qt.我熟悉Qt,并且已经将框架移植到Qt.但是问题是我必须在框架内进行过多的Qt集成,而这不是我想要的.我想用Qt及其GUI元素控制可视化,但是对视图的绘制调用应该由我的Visualization类进行,如GLUT示例所示.因此,必须有一种给继承的QGLWidget指向视图对象的指针的方法,并且每当绘制视图时,小部件都必须调用makeCurrent(),以便glCommands可以在上下文上绘制. 我还可以使用一种纹理,在该纹理中我的视图绘制当前场景,然后在QGLWidget的paintGL或glDraw()函数中绘制该纹理,但是当视图不了解时如何将Widget告知update()关于它. 我将把QTimer设置为0来模拟主循环.我要做的就是能够从我的框架内部触发QGLWidget的呈现.有什么建议吗?链接?例子吗?

so now my problem is I want to use Qt with several windows (QDialogs+QGLWidgets). I am familiar with Qt and I already ported the framework to Qt. but the problem is that I have to do too much Qt integration within the framework and this is not what I want. I want to control the visualization with Qt and its GUI elements, but the draw call for a view should be made by my Visualization class as shown by the GLUT example. So there must be a way to give an inherited QGLWidget a pointer to a view object and whenever the view should be drawn the widget has to call makeCurrent() so the glCommands can draw on the context. I also can use a texture in which my view paints the current scene and then draw the texture in the paintGL or glDraw() function of the QGLWidget, but how can I tell the Widget to update() when the view has no knowledge about it. I will emulate the main loop with a QTimer set to 0. all I want to do is to be able to trigger the rendering of the QGLWidget from inside my framework. any suggestion? links? examples?

推荐答案

因此,必须有一种方法可以为继承的QGLWidget提供指向视图对象的指针以及何时应绘制视图

So there must be a way to give an inherited QGLWidget a pointer to a view object and whenever the view should be drawn

如果从QGLWidget::paintGL内部调用demo_app::display(),它将起作用并将场景绘制到QGLWidget上下文中.但是,这将使用QGLWidget的上下文,因此您需要将所有初始化函数移到QGLWidget中.我不记得是否可以在上下文之间共享OpenGL对象,但是如果做不到就不会感到惊讶.

If you call demo_app::display() from within QGLWidget::paintGL, it will work and will draw scene onto QGLWidget context. However, this will use QGLWidget's context, so you'll need to move All initialization functions into QGLWidget. I don't remember whether OpenGL objects can be shared across context, but won't be really surprised if this can't be done.

但是当视图不了解时,如何告诉窗口小部件进行update().

but how can i tell the Widget to update() when the view has no knowledge about it.

好吧,在视图中添加指向QWidget的指针并调用QWidget->update().应该很明显.

Well, add pointer to QWidget to the view and call QWidget->update(). Should be obvious.

如果要在基于GLUT的窗口中绘制qt小部件...

即如果您想将Qt小部件嵌入"到GLUT窗口中.

I.e. if you want to "embed" Qt widgets into GLUT window.

每个Qt小部件都有render方法.您可以使用此方法将窗口小部件绘制到任何QPaintDevice或任何QPainter上.

Every Qt widget has render method. You can use this method to draw widget onto any QPaintDevice or using any QPainter.

因此,要从框架中绘制窗口小部件,必须将其中之一提供给窗口小部件并手动调用render.

So, to draw widget from within the framework, you'll have to provide one of those to the widget and call render manually.

您还必须转发框架中的鼠标和键盘事件,并将其转换为Qt事件.

You'll also have to forward mouse and keyboard event from the framework and convert them into Qt events.

这应该可行,但实施起来会很痛苦.

That should be doable but it will be major pain to implement.

另请参见 EmbeddedDialogs 演示和 如果您只想使用除glut窗口之外的GUI窗口小部件,而不必将其嵌入glut窗口中...

将与框架和glut消息相关的所有内容包装到QObject中,并将glut消息处理放入此对象的插槽中.将此插槽连接到以0超时运行的计时器.

Wrap everything related to your framework and glut messages into QObject, and put glut message handling into this object's slot. Connect this slot to a timer running with 0 timeout.

我的代码中的示例(使用SDL):

Example from my code (uses SDL):

class Game: public QObject{
Q_OBJECT
protected:
    void processSdlEvents();
...
protected slots:
    void onGameEnd();
    void timerSlot();
...
};

Game::Game(/*arguments*/ ...){
...
    gameTimer = new QTimer(this);
    gameTimer->setSingleShot(false);
    gameTimer->setInterval(0);
    connect(gameTimer, SIGNAL(timeout()), this, SLOT(timerSlot()));
...
}

void Game::timerSlot(){
    processSdlEvents();
    update();
    render();
}

void Game::processSdlEvents(){
    SDL_Event event;
    QList<GameEventHandler*> eventHandlers = findChildren<GameEventHandler*>();
    /*WARNING: This is NOT an infinite loop. */
    while (SDL_PollEvent(&event) != 0){
        if (event.type == SDL_QUIT){
            emit gameEnded();
            continue;
        }
        bool processed = false;
        for (int i = 0; i < eventHandlers.size(); i++){
            if (eventHandlers[i]->processEvent(&event)){
                processed = true;
                break;
            }
        }
        if (processed)
            continue;
        for (int i = 0; i < joysticks.size(); i++){
            if (joysticks[i]->processEvent(&event)){
                processed = true;
                break;
            }
        }
        /*if (processed)
            continue;*/
    }
}


int main(int argc, char** argv){
    QApplication app(argc, argv);
    int result = 0;
    try{
        Game game;
        QObject::connect(&game, SIGNAL(gameEnded()), &app, SLOT(quit()));
        game.start();
        result = app.exec();
    }
    catch(const QString& s){
        reportException(s);
    }
    catch(std::exception& e){
        reportException(e);
    }
    catch(...){
        reportException();
    }
    return result;
}

请注意,processSdlEvents不是无限循环.偶尔会调用它,并处理自上次调用以来收到的所有事件,然后终止.

Please note that processSdlEvents is NOT an infinite loops. It gets called once in a while and processes all events received since the last call and then terminates.

在这种情况下,您的框架特定功能是从Qt主循环中调用的.

In this scenario your framework specific functions are called from within Qt main loop.

您也可以采用其他方法,并在自己的框架(使用QEventLoop类或QApplication::processEvents())中从主循环调用特定于Qt的函数,但是它可能不太可靠,我还没有尝试过我自己.

You could also probably do it other way around and call Qt-specific functions from main loop in your own framework (using either QEventLoop class or QApplication::processEvents()) but it might be less reliable and I haven't tried that myself.

这篇关于将Qt集成到预先编写的应用程序/框架中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆