GTK+ Forums

Discussion forum for GTK+ and Programming. Ask questions, troubleshoot problems, view and post example code, or express your opinions.
It is currently Mon Dec 22, 2014 3:38 pm

All times are UTC




Post new topic Reply to topic  [ 4 posts ] 
Author Message
 Post subject: C++ and GTK - Program architecture
PostPosted: Thu Dec 08, 2011 7:27 pm 
Offline
Familiar Face

Joined: Tue Mar 16, 2010 9:35 pm
Posts: 24
Ok, I admit it. This is confusing, and I'm not too fond of reading tons of documentation - it takes more time than I usually have. However, I often butt my head against the wall, and I'm doing that now. I'm trying to create an elevator simulator using C++ and GTK. But I'm having problems with the program architecture and the functionality of the program and the GUI, and how to tie these together.

What I originally thought was something like this:
driver (file with main()): This instantiates the GUI from a gui class, and an elevator object from an elevator class. Then it has logic for controlling the elevator (through public functions in the elevator object), and for updating the GUI (through public functions in the GUI class).

gui (.cpp/h): Contains the GTK code for the whole GUI: widgets, signal handlers, public access methods for updating the widgets etc.

elevator (.cpp/h): Contains the elevator functions, like keeping track of the current floor, the queue, moving the elevator etc. Also contains, of course, public access methods for receiving a new floor to add to the queue, return the current floor etc.

driver.cpp:
Code:
#include <iostream>
#include <gtkmm.h>
#include "Egui.h"
#include "Elevator.h"

using namespace Glib;

int main (int argc, char *argv[]) {
        Glib::RefPtr<Gtk::Builder> builder;
        Gtk::Main kit(argc, argv);
   
        // load the interface
        builder = Gtk::Builder::create();
        builder->add_from_file("src/Egui.glade");

        // Get the main window:
        Egui *mwindow;
        builder->get_widget_derived("mwindow", mwindow);

        Elevator *elevator1;                                    // - Create an object of the Elevator class. This will be our elevator for
        elevator1 = new Elevator();                             //   this simulation.
        int f = elevator1->getCurrentFloor();                   // - Get the currect floor from the elevator (ask it which floor it's on).
        mwindow->setCrrntFloorEnt(5);                           // - Set the currect floor in the gui (the Egui object *mwindow created above.)

        // Everthing above this line is executed BEFORE the GUI is started. Hence, there can be no logic here.
        // start the event loop
        Gtk::Main::run(*mwindow );
        // Everthing after this line never happens, unless the gui is terminated. Hence, there can be no logic here either.
        // The logic should be INSIDE the main program loop, but how?

        return 0;
}


Egui.cpp:
Code:
#include "Egui.h"
#include "Elevator.h"
#include <iostream>

using namespace Glib;

Egui::Egui (BaseObjectType* base_object, const Glib::RefPtr<Gtk::Builder>& m_refBuilder):Gtk::Window(base_object) {
        m_refBuilder->get_widget("mwindow", mwindow);
        m_refBuilder->get_widget("f5bttn", f5bttn);
        m_refBuilder->get_widget("f4bttn", f4bttn);
        m_refBuilder->get_widget("f3bttn", f3bttn);
        m_refBuilder->get_widget("f2bttn", f2bttn);
        m_refBuilder->get_widget("f1bttn", f1bttn);

        m_refBuilder->get_widget("crrntfloorntr", crrntfloorntr);

        // Connect the appropriate callbacks... (no signals defined in the Glade file...)
        f5bttn->signal_clicked().connect(sigc::mem_fun(*this, &Egui::on_f5bttn_clicked));
        f4bttn->signal_clicked().connect(sigc::mem_fun(*this, &Egui::on_f4bttn_clicked));
        f3bttn->signal_clicked().connect(sigc::mem_fun(*this, &Egui::on_f3bttn_clicked));
        f2bttn->signal_clicked().connect(sigc::mem_fun(*this, &Egui::on_f2bttn_clicked));
        f1bttn->signal_clicked().connect(sigc::mem_fun(*this, &Egui::on_f1bttn_clicked));
}

// Signal handler methods:
void Egui::on_f1bttn_clicked () {
        std::cout << "Mmmmm.....1......" <<std::endl;
}
void Egui::on_f2bttn_clicked () {
        std::cout << "Mmmmm.....2......" <<std::endl;
}
void Egui::on_f3bttn_clicked () {
        std::cout << "Mmmmm.....3......" <<std::endl;
}
void Egui::on_f4bttn_clicked () {
        std::cout << "Mmmmm.....4......" <<std::endl;
}
void Egui::on_f5bttn_clicked () {
        std::cout << "Mmmmm.....5......" <<std::endl;
}

// Set the current floor in the text entry field:
void Egui::setCrrntFloorEnt (int floor) {
        std::ostringstream ostr;
        ostr << floor;
        ustring f = ostr.str();
        crrntfloorntr->set_text(f);   
}

Egui.h:
Code:
#ifndef EGUI_WINDOW_H
#define EGUI_WINDOW_H

#include <gtkmm.h>

class Egui:public Gtk::Window {
        public:
        virtual ~Egui ();
        Egui (BaseObjectType* cobject, const Glib::RefPtr<Gtk::Builder>& m_refBuilder);
        void setCrrntFloorEnt (int);
        void testMethod ();

        //protected:
        Gtk::Window    *mwindow;
        Gtk::Button    *f1bttn,   
        *f2bttn,
        *f3bttn,
        *f4bttn,
        *f5bttn;
        Gtk::Entry   *crrntfloorntr;   

        void on_f1bttn_clicked ();
        void on_f2bttn_clicked ();
        void on_f3bttn_clicked ();
        void on_f4bttn_clicked ();
        void on_f5bttn_clicked ();
};

#endif // EGUI_WINDOW_H

Elevator.cpp:
Code:
#include "Elevator.h"
#include <iostream>

using namespace std;

Elevator::Elevator () {
        currentfloor = 1;
        queue[0] = 2; queue[1] = 5; queue[2] = 3; queue[3] = 4; queue[4] = 2;
}

Elevator::~Elevator () {}

int Elevator::getCurrentFloor () {
        return currentfloor;
}

void Elevator::setCurrentFloor (int floor) {
        currentfloor = floor;
}

void Elevator::moveElevator () {
        setCurrentFloor(queue[0]);
        sleep(2);
        setCurrentFloor(queue[1]);
        cout << "Done." <<endl;*/
}

Elevator.h:
Code:
#ifndef ELEVATOR_H
#define ELEVATOR_H

class Elevator {
        public:
        Elevator ();
        virtual ~Elevator ();
        int getCurrentFloor ();
        void setCurrentFloor (int);
        void moveElevator ();

        protected:
        int currentfloor;
        int queue[5];
};

#endif // ELEVATOR_H


And so on. This is of course just simple test code/functions, created to find out how to tie things together.

This is obviously not working, I'm thinking wrong, and I need professional help.

As I mention in the comments, I cannot have the code that runs the elevator, ie. presses a floor button and sends the floor to the elevator, then tells it to run (or just continue running while blah-blah), in the main() function (driver.cpp). At least, not how the code is structured at the moment.

Also, I cannot have it in the GUI class (Egui), since everything put inside the constructor of that class will run before the main() function (in driver.cpp) runs/starts the GUI.

So, my question here is: How to I structure this? What is the correct architecture here? What should I do (possibly fundamentally) different here?


Top
 Profile  
 
 Post subject: Re: C++ and GTK - Program architecture
PostPosted: Fri Dec 09, 2011 6:50 pm 
Offline
Never Seen the Sunlight

Joined: Mon Apr 28, 2008 5:52 am
Posts: 799
Location: UK
Hi,

First you must remember that GTK in event driven (in fact most GUIs are event driven), it does not matter what programming language you use. So all operations of your elevator will be initiated from a button press in your GUI, which simulate the buttons on each floor and the elevator. One thing you must not use is sleep() in your call backs as that would freeze your application and your GUI will not respond for that set time. If you need a delay use Glib::SignalTimeout::connect() to connect a call-back which will be called after a set delay.

One thing that you will need to do is spend some thing working out the logic for your elevator. So things to think about are which direction it is travelling, is it stopped at a floor, what state are the doors (opened, closed), which floor is it at if any, what buttons have been pressed (on the floor(up, down) or in the elevator (the floor number)).

_________________
E.


Top
 Profile  
 
 Post subject: Re: C++ and GTK - Program architecture
PostPosted: Sat Dec 10, 2011 8:57 am 
Offline
Familiar Face

Joined: Tue Mar 16, 2010 9:35 pm
Posts: 24
Hi, and thanks for the tips.

What I was thinking: Do I need to use threads in an "application" like this? I mean, the elevator should move independently of the GUI, but that's maybe not possible, because of the way GTK (and most other gui's) work? Ideally, the elevator should just keep moving by itself, based on a queue of destinations (and an algorithm that makes this effective). Then the GUI should just press the relevant buttons to add a floor to the elevator's queue, get the elevator's current floor etc. etc.


Top
 Profile  
 
 Post subject: Re: C++ and GTK - Program architecture
PostPosted: Sat Dec 10, 2011 7:59 pm 
Offline
Never Seen the Sunlight

Joined: Mon Apr 28, 2008 5:52 am
Posts: 799
Location: UK
You could use threads, but in this simple case you could just use a simple timer callback. Using threads brings in its own complications such as how to communicate between threads, locking, etc.

With you elevator you should think of it as a state machine. The states are which direction it is moving (up, down, stopped at a floor), if stopped at a floor doors opened or closed, where the elevator is (which floor or between floors), what buttons are pressed and active. So you could use a time-out using Glib::SignalTimeout::connect() or Glib::SignalTimeout::connect_seconds() to connect the call-back, which would be called every X milli seconds/seconds. In the call-back this will alter the state of the elevator state machine. So reacting to what the pressed buttons, moving the elevator, opening/closing the doors, etc.

_________________
E.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 4 posts ] 

All times are UTC


Who is online

Users browsing this forum: Google [Bot] and 3 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group