Re: What is the minimum number of lines to update a gui window without user clicking a button



I may be able to eventually figure out how to do it from your example, but at present it doesn't appear to have the ability to append text, except for an initial text and one addition.

I'm trying to be able to arbitrarily update the text numerous times (just like you would with "cout").

I thought the dispatcher() function would work reusable like the gprint() function I'm trying to create.  It appears to work correctly the first time.

The other updates doesn't occur when the dispatcher() function is called.  The gui window becomes non responsive and dimmed until all the functions are completed, then everything is showed at once.  The window at the end of the operation becomes a normal gui.

Kjell's example works exactly as intended, except that it has many widgets and I can't figure out how to remove the widgets without breaking the code.  Also it requires a clicking of a button to start.

I realize that, everything that a person needs is included in his example.  My problem is being able to isolate a basic screen and an update.

I know that I'll eventually understand it, and I'd be able to break it down for anyone else that might have problems with it, and reuse the many components in various applications.

I realize how easy it would be for you and other experts to use his example.  But I can't figure out where to put my function and output a single line to the gui, then perform a followup after some operations.

I also appreciate the your reference to how complicated this task is.  Hopefully I can contribute to making something complicated, easy for the next person.

I added my example, using your code to demonstrate the problem that I'm having.  I'm sure I'm misusing the dispatcher() function.  But I don't see any other way to update the gui from your example.

Thanks again for your contribution and input!

// Code begin
// --------------------------------------------------------------------------------------
#include <gtkmm.h>
#include <unistd.h> /* for sleep() */
#include <iostream>

using namespace std;

class Example {

string textdata = "uninitilzed";

private:
    Glib::RefPtr<Gtk::Application> app;
    Gtk::Window                    win;
    Gtk::TextView                  tv;
    Glib::RefPtr<Gtk::TextBuffer>  tb;
    Glib::Dispatcher               dispatcher;
    Glib::Threads::Thread         *thread;

   /* This function is called on a separate thread so as to avoid
    * blocking GTK+'s main loop.
    */
   void blocking_operation() {
        /* This simulates a "blocking" process */
        sleep(5);

        textdata += "First function is complete.\n";

        /* When the process is finished, we "notify" the GTK+ Main Loop by
         * using the dispatcher */
        dispatcher();

        sleep(5);
        textdata += "Second function is completed.\n";
        dispatcher();

        sleep(5);
        textdata += "Third function is completed.\n";
        dispatcher();

        sleep(5);
        textdata += "Fourth function is completed.\n";
        textdata += "This next funtion may take up to three hours to complete.\n";
        dispatcher();

        sleep(60);
        textdata += "Fifth function is completed.\n";
        dispatcher();
   };

    /* This function is called on GTK+'s main loop via a
     * Glib::Dispatcher */
    void blocking_operation_finished() {
        cleanup_thread();
        tb->set_text(textdata);
    };

    void cleanup_thread() {
        /* We must call Glib::Threads::Thread::join() in order to
         * correctly clean up the resource. */
        if (thread) {
            thread->join();
            thread = NULL;
        }
    }

public:
    ~Example() {
        /* This will prevent the Window from being closed while
         * the blocking operation is ongoing. */
        cleanup_thread();
    }

    Example(int argc, char *argv[]) : app(Gtk::Application::create(argc, argv, "com.example")), tb(tv.get_buffer()), thread(NULL)
    {
        /* Create a slot (a.k.a. functor) to the
         * blocking_operation_finished() member function for the
         * dispatcher to execute.
         */
        sigc::slot<void> op_finished_functor = sigc::mem_fun(this, &Example::blocking_operation_finished);

        /* The dispatcher will be used when the operation has finished.
         * Here we set the function the dispatcher will call on the "main
         * thread" -- a.k.a. GTK+'s Main Loop.
         */
        dispatcher.connect(op_finished_functor);

        /* Now set the text in the buffer.
         */
        textdata = "Starting application.\n";
        tb->set_text(textdata);

        win.add(tv);
        win.show_all();
    }

    void run() {
        /* Create a slot to the blocking_operation() member function
         * to pass to Glib::Threads::Thread::create().
         */
        sigc::slot<void> op_functor = sigc::mem_fun(this, &Example::blocking_operation);

        /* Create a worker thread to perform the blocking_operation
         * function.
         */
        thread = Glib::Threads::Thread::create(op_functor);

        app->run(win);
    }
};

int main(int argc, char *argv[]) {
    Example example(argc, argv);

    example.run();
    return 0;
}
// --------------------------------------------------------------------------------------
// code end



-- L. James

--
L. D. James
ljames apollo3 com
www.apollo3.com/~ljames

[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]