Questions about QApplication::processEvents and why doesn't it work on Windows (MinGW)
-
Hi,
I am writing an application called Oplot, which is a graphical toolkit for GNU Octave. For now GNU Octave handles both FLTK and gnuplot as graphical toolkit. On Linux it works pretty good, but on Windows (MinGW) it doesn't work at all.
On Windows (MingGW - 4.8.0) the oplot window becomes non-responsive for user manipulations, but yet it receives and plots data in the window. Everything looks nice and responsive, until i put the mouse cursor on the gui....Then it becomes non-responsive, and mouse cursor indicates that it's busy.
If I leave the "busy" mouse cursor on oplot window, and do x = -pi:pi/20:pi; plot(x,sin(x)); then oplot shows a nice sine curve, and the mouse cursor changes to the arrow. When I try to activate the oplot window by clicking on the window, then it becomes busy again.Link to oplot code that creates the problem: "oplot_backend.cc":http://sourceforge.net/apps/trac/oplot/browser/trunk/octave/oplot_backend.cc
Link to "Oplot":http://sourceforge.net/apps/trac/oplot/browser/trunk project.
Octave is a single thread application, and is not thread-safe at all, and the graphical objects to be plotted is organized in a root -> figure -> axes -> line | surface | mesh | bar | light structure.
Creation of figures and axes and line is done in that spesific order, and a redraw is done by inheritance.
Initializing of oplot in Octave is done in octave prompt by: graphics_toolkit("oplot");
graphics_toolkit("oplot") will then call init_oplot, which is an octave-shared-object. A C++ compiled module.@
DEFUN_DLD ( init_oplot, , , "" ) {if ( ! backend_registered ) { mlock (); app = new QApplication ( argc, const_cast<char**> ( argv ) ); Q_INIT_RESOURCE ( oplot ); if ( !QGLFormat::hasOpenGL() ) { QMessageBox::information ( 0, "OpenGL is not installed on the system", "This system does not support OpenGL. Please find an usable OpenGL implementation!" ); } app->setQuitOnLastWindowClosed ( false ); graphics_toolkit::register_toolkit ( new oplot_graphics_toolkit ); backend_registered = true; octave_value_list args; args ( 0 ) = "__redraw_oplot__"; feval ( "add_input_event_hook", args, 0 ); } octave_value retval; return retval;
}
@This will create a oplot window, by calling ctor of oplot_graphics_toolkit
@
oplot_graphics_toolkit ( void )
: base_graphics_toolkit ( OPLOT_GRAPHICS_TOOLKIT_NAME ) {
window = new OpMainWindow;
}
@The following snippet in init_oplot will create a add_input_event_hook in Octave, which again means that some code is added into the Octave event-loop. This process the Qt events synchronously with events in GNU Octave.
@
octave_value_list args;
args ( 0 ) = "redraw_oplot";
feval ( "add_input_event_hook", args, 0);
@On the other hand, if I put app->exec() after the feval call above, so my code looks like this:
@feval ( "add_input_event_hook", args, 0);
app->exec();
}
@then Octave can't do keyboard events, and then I can't use Octave prompt.
The redraw_oplot is listed below:
@
static int
redraw_oplot ( void ) {
if ( backend_registered ) {
// we scan all figures and add those which use FLTK as a backend
graphics_object obj = gh_manager::get_object ( 0 );
if ( obj && obj.isa ( "root" ) ) {
base_properties& props = obj.get_properties ();
Matrix children = props.get_all_children ();
for ( octave_idx_type n = 0; n < children.numel (); n++ ) {
graphics_object fobj = gh_manager::get_object ( children ( n ) );
if ( fobj && fobj.isa ( "figure" ) ) {
figure::properties& fp =
dynamic_castfigure::properties& ( fobj.get_properties () );
if ( fp.get___graphics_toolkit__ () == OPLOT_GRAPHICS_TOOLKIT_NAME )
window->update_figure ( fp );
app->flush(); // force re-rendering
}
}
}
app->processEvents();
}return 0;
}
@
The code for window->update_figure looks like this:
@
void OpMainWindow::update_figure ( figure::properties& fp ) {
int figure_id = static_cast<int> ( fp.get___myhandle__().value() );
if ( figure_id > 0 && !m_FigureManager->exists ( figure_id ) ) {
m_FigureManager->add_figure ( fp );
QRect g = frameGeometry();
resize ( g.x() , g.y() - y(), g.width(), g.height() );
}}
@And figuremanager->add_figure looks like this
@
void OpFigureManager::add_figure ( figure::properties& fp ) {
print_debug ( "OpFigureManager::add_figure\n" );
OpFigureWindow *win = new OpFigureWindow ( fp );
int handle = static_cast<int> ( fp.get___myhandle__ ().value () );
m_tabs->insertTab ( handle-1, win, QString ( fp.get_title().c_str() ) );
m_tabs->setCurrentWidget ( win );
win->show();
}
@Any suggestions on why this works on Linux and not on Windows (MinGW)?
Why does Windows gives me an non-responsive gui, and not Linux?
What can I do to make it work on Windows as well?Best regards,
Ole J. Hagen
-
Hi, again.
I'm still struggling. I suspected that the processEvents didn't work properly, so I tested out another application I wrote for MSVC-10 Qt 4.8.0, which is a broadcast forwarder application.
This application, qlink works perfectly both with Qt-4.8.0 on MinGW and MSVC-2010.But in qlink, starts the Qt event loop with QApplication::exec(), while it seems like it that Qt event loop on MinGW starts properly. If I could compile Octave on Windows with MSVC-2010, I would checked it out....But this is not possible.
Ole