gtkmm: needing parallel program loop

47 Views Asked by At

I am building a program in c++ using gtkmm 4 for the user interface. Working in Linux(Fedora). All of the UI is in a class (called 'Screens') that inherits Gtk::Window. I am using the 'standard' program for 'main':

#include "Screens.h"
#include <gtkmm/application.h>

int main(int argc, char *argv[])
{
  auto app = Gtk::Application::create("com.wrlee");

  //Shows the window and returns when it is closed.
  return app->make_window_and_run<Screens>(argc, argv);
}

All of the gtkmm structure for the UI is defined in the class definition of the Screens class.

The idea is that there will only ever be a single instance of Screens, one that defines the UI and then provides member functions to insert data into the screen image as the application runs.

It seems that the obvious solution is to have the Screens class be comprised only of static elements, but that cannot be done since the inheritance of the Gtk::Windows class precludes marking the Screens class and all its components static. So the Screens class is coded like a "normal" class with constructor/destructor and a host of member functions to manipulate the screen.

Trying to compile and run the code, several problems I've run into and things I've learned.

... The template 'make_window_and_run(argc, argv)' requires the class (Screens in my case) to be a Gtk::Window.

... The template 'make_window_and_run(argc, argv)' requires the constructor to be public.

... The template 'make_window_and_run(argc, argv)' creates an instance of Screens, executing the constructor. In my case, the UI is built and appears on the screen. Good! But .... the template 'make_window_and_run(argc, argv)' doesn't return to the 'main' until the Gtk::Window of the Screens instance is finished.

... This creates the first problem: I have a whole application that needs to go ahead and run, doing other 'things' (e.g., accessing serial and parallel port data), with results showing up on the screen in the Screens UI. (I call this the 'Do_It' code.) In other environments, this would be the code accessed from 'main' after initializing the UI,but in the gtkmm, the program never gets to that state. So: the question is... how to make my application go ahead and run the Do_It code after the gtkmm UI is created?

Things I have tried over the past 4-5 days of flailing at the problem: One FLAIL:

... At the beginning of 'main' I created a thread that would execute the Do_It code. This thread would wait for a message/signal/whatever from the Screens object when the UI is built, allowing the Do_It to start operating. The result was that when the Do_It code makes the first call to Screens methods, a second Screens instance is constructed, constructor execution happens, apparently creating a second Gtk::Window off in the ether, and all of the calls to the Screens instance appear to be directed there and never show up on the display.

... I installed a singleton in Screens, trying to prevent a second instance from being created. No luck. Apparently the thread for the Do_It code gets copies of the files, etc, for its own use, and the first Screens member function call still causes the second Constructor execution and the ghost UI. Probably tied up with the requirement by the template for a public constructor.

A second FLAIL:

I modified the constructor of Screens so that the Do_It code was called at the end of the constructor. No luck since the Gtk::Window being created by the Screens constructor is not 'realized' (i.e., opened and displayed on the screen) until the constructor is finished. And in my case, that doesn't happen since the Do_It is in itself a looping/always running piece of code that runs until sometime in the future an external event is seen that causes it to quit.

I am at a loss for further investigation.

Is there some way in a Gtk::Window application to say from the user code "Display the window! Now!"?

Is there any way to prevent the duplicate (ghost) construction of the Screens Gtk::Window?

What is the best way to call the Do_It code into execution once the UI has been created on the screen?

If needed, I can post the Screens class code, plus a set of code I've been using for Do_it until I can get it working and can install the production code there.

All help greatly appreciated.

Regards,

Bill Lee

Please see the original problem description.

0

There are 0 best solutions below