所以必须有一种方法可以给继承的 QGLWidget 一个指向视图对象的指针,并且无论何时应该绘制视图
如果您demo_app::display()
从 inside调用QGLWidget::paintGL
,它将起作用并将场景绘制到QGLWidget
上下文中。但是,这将使用QGLWidget
' 上下文,因此您需要将所有初始化函数移动到QGLWidget
. 我不记得 OpenGL 对象是否可以跨上下文共享,但如果不能做到这一点也不会感到惊讶。
但是当视图不知道它时,我怎么能告诉小部件更新()。
好吧,添加指向QWidget
视图的指针并调用QWidget->update()
. 应该很明显。
如果您想从基于 GLUT 的窗口中绘制 qt 小部件...
即,如果您想将 Qt 小部件“嵌入”到 GLUT 窗口中。
每个 Qt 小部件都有render
方法。您可以使用此方法将小部件绘制到 anyQPaintDevice
或使用 any QPainter
。
因此,要从框架内绘制小部件,您必须向小部件提供其中之一并手动调用渲染。
您还必须从框架中转发鼠标和键盘事件并将它们转换为 Qt 事件。
这应该是可行的,但实施起来会很痛苦。
另请参阅EmbeddedDialogs演示和QGraphicsProxyWidget。
如果您只是想在 glut 窗口之外使用 GUI 小部件,而不是将它们嵌入到 glut 窗口中......
将与您的框架和 glut 消息相关的所有内容包装到QObject
中,并将 glut 消息处理放入该对象的插槽中。将此插槽连接到超时运行的计时器0
。
我的代码示例(使用 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 不是无限循环。它偶尔会被调用一次,并处理自上次调用以来收到的所有事件,然后终止。
在这种情况下,您的框架特定函数是从 Qt 主循环中调用的。
您也可以采取其他方式,并在您自己的框架中从主循环调用 Qt 特定函数(使用QEventLoop
class 或QApplication::processEvents()
),但它可能不太可靠,我自己没有尝试过。