将Qt集成到预先编写的应用程序/框架中 我有一个C++编写的可视化框架,希望使用QT有一个合适的GUI,并控制我的可视化与它们交互。目前,我正在使用GLUT创建一个窗口并在其中绘制视图。所以我所做的一切就是初始化一个类可视化的对象,它为我做了一切:保存模型和视图。视图本身拥有一个控制器来处理用户输入和操纵模型。我的主循环如下所示: 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(); }

将Qt集成到预先编写的应用程序/框架中 我有一个C++编写的可视化框架,希望使用QT有一个合适的GUI,并控制我的可视化与它们交互。目前,我正在使用GLUT创建一个窗口并在其中绘制视图。所以我所做的一切就是初始化一个类可视化的对象,它为我做了一切:保存模型和视图。视图本身拥有一个控制器来处理用户输入和操纵模型。我的主循环如下所示: 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(); },qt,opengl,glut,qglwidget,Qt,Opengl,Glut,Qglwidget,使用GLUT,我有一个窗口,可以在其中排列多个视图。当我命令视图在主循环期间绘制时,我可以执行GLM命令,一切都很好 所以现在我的问题是我想在几个窗口中使用Qt(QDialogs+QGLWidgets)。我熟悉Qt,并且已经将框架移植到Qt。但问题是我必须在框架内进行太多的Qt集成,而这不是我想要的。我想用Qt及其GUI元素控制可视化,但是视图的绘制调用应该由我的可视化类进行,如GLUT示例所示。因此,必须有一种方法为继承的QGLWidget提供一个指向视图对象的指针,并且每当绘制视图时,wid

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

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

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

如果从
QGLWidget::paintGL
中调用
demo\u app::display()
,它将工作并将场景绘制到
QGLWidget
上下文中。但是,这将使用
QGLWidget
的上下文,因此您需要将所有初始化函数移到
QGLWidget
中。我不记得OpenGL对象是否可以跨上下文共享,但如果不能做到这一点,我也不会感到惊讶

但是当视图不知道时,我如何告诉小部件更新()

好的,将指向
QWidget
的指针添加到视图中,并调用
QWidget->update()
。应该是显而易见的

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

也就是说,如果您想将Qt小部件“嵌入”到GLUT窗口中

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

因此,要从框架中绘制小部件,您必须向小部件提供其中一个,并手动调用render

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

这应该是可行的,但实施起来将是巨大的痛苦

另请参见演示和演示

如果您只想在glut窗口之外使用GUI小部件,而不想将它们嵌入glut窗口…

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

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

类游戏:公共QObject{
Q_对象
受保护的:
void processSdlEvents();
...
受保护插槽:
void onGameEnd();
void timerSlot();
...
};
游戏::游戏(/*参数*/…){
...
gameTimer=新的QTimer(此);
gameTimer->setSingleShot(假);
游戏计时器->设置间隔(0);
连接(游戏计时器,信号(timeout()),此,插槽(timerSlot());
...
}
void Game::timerSlot(){
processSdlEvents();
更新();
render();
}
void Game::processSdlEvents(){
SDL_事件;
QList eventHandlers=findChildren();
/*警告:这不是无限循环*/
while(SDL_PollEvent(&event)!=0){
if(event.type==SDL\u QUIT){
发射gameend();
继续;
}
bool-processed=false;
对于(int i=0;iprocessEvent(&event)){
已处理=真;
打破
}
}
如果(已处理)
继续;
对于(int i=0;iprocessEvent(&event)){
已处理=真;
打破
}
}
/*如果(已处理)
继续*/
}
}
int main(int argc,字符**argv){
QApplication应用程序(argc、argv);
int结果=0;
试一试{
游戏;
QObject::连接(&game,信号(gameEnded()),&app,插槽(quit());
game.start();
结果=app.exec();
}
渔获物(常量QString&s){
报告例外情况;
}
捕获(标准::异常&e){
报告例外情况(e);
}
捕获(…){
reportException();
}
返回结果;
}
请注意,processSdlEvents不是无限循环。它每隔一段时间被调用一次,并处理自上次调用以来收到的所有事件,然后终止

在这个场景中,特定于框架的函数是从Qt主循环中调用的


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

我不想调用我的
demo\u app::display()
在QGLWidget中。这应该是我的
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;
}