I know that in order to write a GTK application, I write a bunch of code which describes what is put in the main window, then I call:
gtk_main();
Any code statements after this do not get executed.
Now let's suppose I'd like my GTK app to display something I wrote with glut, which itself contains a bunch of statements about what graphics need to be set etc. then ends with the statement:
glutMainLoop();
Anything after this is not executed.
So my problem is that either of these two statements prevents me from calling the other.
Is there a way to execute a glut main loop inside a GTK widget ?
Is there a way to write a code that could somehow simultaneously call both a GTK main loop and a glut main loop (but called from the main program and rendered in a separate X window, not within a widget)? I've got a feeling this could be done with "threads"...
You don't. There's generally no point to it.
GLUT is a library for creating and managing OpenGL windows. GTK already has an OpenGL window in it. If you're using GTK, then there's no point in using GLUT. It's like having two vector math libraries or something.
You are running the main loops. gtk_main() runs until gtk_quit() is called.
gtk_main() at GTK.org
Runs the main loop until gtk_main_quit() is called. You can nest calls to gtk_main(). In that case gtk_main_quit() will make the innermost invocation of the main loop return.
Also, glutMainLoop() works the same way, it processes GL events forever.
glutMainLoop() at OpenGL.org
glutMainLoop() enters the GLUT event processing loop. This routine should be called at most once in a GLUT program. Once called, this routine will never return. It will call as necessary any callbacks that have been registered.
So, you you wan't both of these things to execute at the same time (I think they might interfere with each other so you might get unexpected results) then you will need to call gtk_main_iteration() from inside glut.
gtk_main_iteration() at GTK.org
Runs a single iteration of the mainloop. If no events are waiting to be processed GTK+ will block until the next event is noticed. If you don't want to block look at gtk_main_iteration_do() or check if any events are pending with gtk_events_pending() first.
Now.. GLUT doesn't have an equivalent to gtk_main_iteration() so you are going to need to register GLUT callbacks.
You could register a callback with GLUT that runs gtk_main_iteration() using glutIdleFunc(void (*func)(void)) which will run a callback for every frame - glutIdleFunc()..
Or you could give a callback to glutTimerFunc(unsigned int msecs,
void (*func)(int value), value) to call and check the return value of gtk_main_iteration() every 200msec or so.
I'd probably experiment with both, glutIdleFunc() might not always get called regularly enough for good responsiveness.
It really is worth looking at driving GTK's GL support though.
Related
We have a significantly multi-threaded embedded Qt application. However the bulk of it's processing is done in the main thread (i.e.: first started), which obviously also handles the screen painting. For inter-thread communication, a truckload of signal/slot calls are used.
Everything works fine, until the CPU-load hits a certain point, and then the screen stops updating. It doesn't matter what happens to cause the load - more data arriving, more detailed record-processing, extra logging, etc.
From the logs, I can see the main program loop executing many times a second, and while the CPU load is low - I also see the log from one of the widget paint() functions - every iteration. When the load gets too high, I still see the main loop executing, but the widget paint() functions are not called (and the screen is not updating).
Is this a known bug?
Is there some way to debug this further?
Is there a way to absolutely force a screen refresh?
I suspect that possibly some kind of signal/slot handling is starving the paint of CPU time. I imagine the signal interrupting the paint somehow, but before the handling is done, another signal arrives. Do signals/slots work like this?
EDIT: Based on #Jeremy Friesner's comments below, so far I've tried:
// KLUDGE: TRY TO FORCE A REPAINT
// QCoreApplication::postEvent( this, new QEvent(QEvent::UpdateRequest), Qt::HighEventPriority );
QCoreApplication::sendEvent( this, new QEvent(QEvent::UpdateRequest) );
qApp->processEvents();
To no avail.
EDIT2:
Also tried:
//QCoreApplication::postEvent( this, new QEvent(QEvent::Paint), Qt::HighEventPriority );
QCoreApplication::sendEvent( this, new QEvent(QEvent::Paint) );
qApp->processEvents();
So I've recently started dabbling a bit with the Qt animation framework and I'd say everything goes pretty well, however now I'd like to make it so that a function gets called after an animation finishes, is this possible?
I've already tried executing the function after the animation starts, however this doesn't seem to work (I presume because Qt animations are ran on a separate thread)
The way I've tried this is very simply like this:
AnimIn->setDuration(500);
AnimIn->setStartValue(0.f);
AnimIn->setEndValue(1.f);
AnimIn->setEasingCurve(QEasingCurve::InCubic);
AnimIn->start();
MyFunction();
I've tried looking through the Qt documentation but to no avail, seeing that pretty much everything about animation and Qt is in QML which I don't use.
You'll need to listen to the finished() signal from your animation. Here's how you'd connect the signal:
QObject::connect(AnimIn, &QAbstractAnimation::finished, this, &YourClass::OnAnimFinished);
where OnAnimFinished() is obviously a slot in your current class. When the animation finishes, the signal will be emitted and the slot will be invoked. Then in the body of the OnAnimFinished() function you can call MyFunction().
I'm using glutMouseFunc(mouseFunction); as a callback however I keep getting the Access violation reading location 0x000000b0 at this line glutMouseFunc(mouseFunction);
I'm not using any of the glutInit functions because they interfere with the program and they are not essential anyways.
Does anyone know why I'm getting this error when at this callback?
Here is my initialize function:
int Initialize()
{
/* Bunch of code here that is irrelevant to the problem.......*/
glutMouseFunc(mouseFunction); // Error occurs here.
}
And here is my mouseFunction:
void mouseFunction(int button, int state, int x, int y){
if(button==GLUT_MIDDLE_BUTTON && state==GLUT_DOWN)
{
printf("Pressed middle mouse button!");
}
}
I've noticed one thing though, there error does not occur when I call the mouseFunction() as a normal function call in my Initialize method however once I try to use the mouseFunction with glutMouseFunc(mouseFunction), than the error happens so I believe this is more of an error with glutMouseFunc.
I'm not using any of the glutInit functions because they interfere with the program and they are not essential anyways.
This is your problem. If you're going to use GLUT, use it correctly.
The glutInit() function is essential - part of what it does is initializing internal state within GLUT. As you've discovered, with this state not properly initialized, other parts of GLUT (such as mouse event handling!) may not work properly.
Given your comments to the other questions your problem is simply, that you call glutMouseFunc without a GLUT window. Trying to register GLUT event callbacks without proper initialization or without a GLUT window created will crash your program.
You also say "GLUT interferes" with your actual window. So why would you try to register a GLUT callback at all if you don't have a window that could actually receive the events for GLUT to dispatch?
You should use the mouse event handling of the window you've already got. And what are you using GLUT for then anyway? The whole purpose of GLUT is to create a window for you and do event management. If you don't use GLUT for that, then don't use GLUT at all.
If it's for the teapot, well, you can have that without GLUT as well.
My program takes a few seconds to start up. I am using clutter for the GUI, and I decided to try and make something pop up to indicate that the program is starting up. I wanted to just have a logo pop up and rotate, then disappear when the program starts.
So in clutter, I figured I could just make a new stage (window) add an actor to it, make the and actor spin, in the first section of the main function. The window will pop up right away, but with no content, but the content wont show until you launch the clutter main loop.
So I was just wondering how I might be able to achieve this using clutter or GTK+.
If you are familar with reaper 4, the audio recording program, this program does something similar to what I want to mine to do.
What you want is called a splash screen. I'm unfamiliar with clutter, but I found this GTK splash screen example.
However, I think you're taking the problem the wrong way. Splash screens are a bad idea because you just add overhead. What you need is improving your startup performance, by doing some CPU and/or IO profiling. Loading stuff on-demand, and not all at once will help.
Unfortunately I'm unfamiliar with Clutter. But I'm pretty sure it will be difficult to render an animation without a main loop running in any high level library.
I'd try to put the code that causes the delay into a separate thread and inform the main loop when the startup is done.
Something like this is what i use:
string splashfile = path_templ + "/splashimg.png";
GtkWidget *image=gtk_image_new_from_file(splashfile.c_str());
gtk_container_add(GTK_CONTAINER(SplashWindow), image);
gtk_widget_show_all(SplashWindow);
//Cycle through all iterations (refresh everything in the GUI)
while (gtk_events_pending()){
gtk_main_iteration();
}
sleep(1);
(... rest of code ...)
gtk_main ();
gdk_threads_leave ();
Especially that last part of while events pending is the key
I have a program that uses GLUT for its OpenGL rendering. Now I need it to be inside of a MFC project so that it can work with another program component.
I've followed this tutorial: http://www.codeguru.com/cpp/g-m/opengl/openfaq/article.php/c10975__1/Setting-Up-OpenGL-in-an-MFC-Control.htm
I am calling the function that was the GLUT display callback when the timer fires, but that's not working because the rendering depends on something that happens in the GLUT idle callback. I don't understand where I should call the GLUT idle callback in my MFC program. Is there a separate event handler I should make for it, and if so, which event? Or am I doing something else completely wrong? I'm fairly familiar with OpenGL but this is my first experience with MFC so I am probably erring on that side.
Thanks so much for your time; I really appreciate it!
I just browsed the tutorial you've linked to; on page two, something along the following lines can be found (I cleaned up the code a little bit):
void COpenGLControl::OnTimer(UINT nIDEvent)
{
if(nIDEvent==1)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
oglDrawScene();
// try to insert your idle function code here
SwapBuffers(hdc);
}
CWnd::OnTimer(nIDEvent);
}
So, basically this is the replacement for glutIdleFunc suggested by the tutorial. I'd simply try to insert the code called in your idle function before the call to SwapBuffers.
I hope that helps.