Re: How to update both the Console and the GTKMM gui window after running other functions



Hi, Alan.  I'm a little embarrassed at the code I'm showing you.  I'm still stuck, but I'm sure I have the gist.  I can figure it out from here.  It's just a matter of time in looking at all the examples from the gtkmm documentation and filling in the glitches I have here.

I'm very self-taught in programming.  I started out with “C” like most people of my era, before C++ came along.  I migrated to C++, kicking and screaming, resisting change.  I'm still getting the grip on classes and class structure.

The current code doesn't compile.  It doesn't do anything much yet (except out put to the console as you suggested as a start in your previous message).

I used “label” instead of “frame”, because I'm currently more familiar with the label data structure (string).

The “*1” and the “*2” comments in the code is where I get error.  I understand this is because I haven't fully implemented the mylabel class yet.

I'll give updates as I come along... and yes, progress is a good thing.  I'm glad for the development of C++ over C.  I appreciate the value, and have been using it for a while, but still learning and getting out   of where I was stuck for a long time, using almost C exclusive in a C++ environment.

// Code (work in progress):
#include <gtkmm.h>
#include <iostream>

using namespace std;

class myLabel: public Gtk::Window
{
// blah blah blah
public:
myLabel();
};

myLabel::myLabel()
{
// myLabel.set_text("hello"); // This line gives errors (*1)
cout << "Hello..." << endl;
}

int main(int argc, char* argv[])
{
    Gtk::Main kit(argc, argv);

    Gtk::Window window;
    Gtk::TextView textview;
    Gtk::Label label;
    myLabel mylabel;


    string mylabeltext = "This is the first line of text in my gui window.\n";

    window.set_default_size(600, 360);
    window.set_title("Gtkmm Programming - C++");
    window.set_position(Gtk::WIN_POS_CENTER);

    label.show();
    window.add(mylabel);

    // mylabel.set_text(mylabeltext); // This line gives errors (*2)

    mylabeltext += "About to run some routines...\n";

    cout << "An initial line has been set to the gui window." << endl;

    Gtk::Main::run(mylabel);

    return 0;
}
// code end

I tried to cleanup my code before posting it.  Of course it's still sloppy.

The Window comes up, but so far, no text in it.

-- L. James

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

On Wed, 2013-07-31 at 08:13 -0700, Alan Mazer wrote:
As I understand it, you just want a window that display the progress of a computation in ASCII readable text.

Here's how I would approach it.

1. Write a program that creates a window.  This should be trivial, something you already know how to do.
2. Derive a class from your window class and use that instead, e.g.,

class myFrame: public Gtk::Window
{
blah blah blah
}

myFrame frame;
Gtk::Main::run(frame);

3. Modify the constructor for myFrame to start a thread, something like this:

Glib::Thread *m_thread = Glib::Thread::create(sigc::mem_fun(*this, &myFrame::dataThread), true);

You'll need to add "void dataThread(void)" to your class.  Just make the thread write to stdout for now.

4. Put your computation in this new thread.

5. Put a scrolling text widget in your window.  Make sure that you know how to write to it.


Now here's where it gets tricky.

You can probably write to the text widget from your thread.  Try it.  In your thread, write stuff to the text widget.

The problem is that you may have a collision between the thread and the main part of the program, e.g., you try to move the window at the same time you're updating the thread.  For that you need to set up a dispatcher.  You should be able to do something like this:

A. Add Glib::Dispatcher m_dispatcher to your class definition.
B. Add a prototype "void dispatcherWork(void);" to your class definition.

C. You're going to link the dispatcher to this routine, so that the routine (dispatcherWork) can be called in the context of the main thread, but by the secondary thread you created.

In your constructor, add m_dispatcher.connect(sigc::mem_fun(*this, &myFrame::dispatcherWork));

D. Make the code in your compute thread that writes to the text widget write to a buffer instead.

E. Create your dispatcherWork() routine.  It should read from the buffer and write to the text widget.

F. In your thread, after you write to the buffer, call the dispatcher like this: m_dispatcher();

When you call the dispatcher, the main thread will update the widget synchronously with other window activities (like moves or repaints) that may be happening.

This is just an outline, but I think this approach is much more productive than messing with signals, since this approach lets you write asynchronously to the window, which I believe is what you want.

-- Alan



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