将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(); }
使用GLUT,我有一个窗口,可以在其中排列多个视图。当我命令视图在主循环期间绘制时,我可以执行GLM命令,一切都很好 所以现在我的问题是我想在几个窗口中使用Qt(将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
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;
}