Chapter 16 Exercise 7 - Program becomes unresponsive when I press "Start"

42 views
Skip to first unread message

Osman Zakir

unread,
Aug 21, 2017, 2:34:23 PM8/21/17
to PPP-public
As the title says, when I press the "Start" button, the program goes unresponsive instead of having the image move.  Also, did I do the "stopping" code correctly?

Anyway, thanks in advance, anyone who decides to help.

And I'll probably go back to the clock program sometime later.  
chapter16ex7.cpp
f-15-2243038_640.jpg

Christiano

unread,
Aug 21, 2017, 10:49:17 PM8/21/17
to PPP-public
You can use my new TimerC:

/* Example using TimerC */
#include "Graph.h"
#include "GUI.h"
#include "Window.h"
#include <iostream>
#include <cmath>
#include <stdexcept>
#include <random>
#include <string>
#include <unistd.h>

using namespace Graph_lib;


inline int rand_int(int min, int max)
{
      unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
      std::default_random_engine generator(seed);

      return std::uniform_int_distribution<int> {min,max}(generator);
}

class TimerC : public Graph_lib::Widget
{
        private:
                double time_interval;
        int state; // working = 1, st,opped = 0

                static void call_back_timer(void *timerc)
                {
                        static_cast<TimerC *>(timerc)->do_it(nullptr, static_cast<TimerC*>(timerc)->own);
                        Fl::repeat_timeout(*static_cast<TimerC *>(timerc), call_back_timer, timerc);
                }
    
                void attach(Graph_lib::Window &win)
                {
                        own = &win;
                }
    
        public:
        // Constructor
        // time = time interval in seconds
        // cb = callback function
        // initial 1 = working at begin / initial 0 = stopped at begin
                TimerC(double time, Callback cb, int initial) :
                        Graph_lib::Widget(Graph_lib::Point{0,0}, 0, 0, "", cb),
                        time_interval{time},
            state{initial}
                {
                        if(state)
                     Fl::add_timeout(time_interval, call_back_timer , this);
                }

        // return time interval
                operator double() const
                {
                        return time_interval;
                }

        // Setup interval
        void set_interval(const int i)
        {
            time_interval = i;
        }

        // Stop timer
        void stop()
        {
            if(state)
            {
                Fl::remove_timeout(call_back_timer, this);
                state = 0;
            }
        }

        // Start Timer
        void start()
        {
            if(!state)
            {
                Fl::add_timeout(time_interval, call_back_timer, this);
                state = 1;
            }
        }

        // Return 1 if timer is working (not stopped)
        // and return 0 otherwise
        int working() const
        {
            return state;
        }

};

class window_timer : Graph_lib::Window
{
public:
    window_timer(Graph_lib::Point xy, int w, int h, const std::string &title);
private:

    TimerC timerx;
    Button ok;
    Button stop;


    // actions invoked by callbacks
    void timer_go();
    void ok_pressed();
    void stop_pressed();

    // callbacks
    static void cb_timer(Address, Address addr) { reference_to<window_timer>(addr).timer_go();}
    static void cb_ok(Address, Address addr) { reference_to<window_timer>(addr).ok_pressed(); }
    static void cb_stop(Address, Address addr) { reference_to<window_timer>(addr).stop_pressed(); }

};

int main()
{
    using namespace std;

    window_timer win{ Point{100, 100}, 600, 400, "Start Stop Moving" };

    return gui_main();

}

window_timer::window_timer(Point xy, int w, int h, const std::string &title)
    :
    Window(xy, w, h, title),
    timerx{0.1, cb_timer, 0},
    ok{Point{0,0}, 100, 50, "Start", cb_ok},
    stop{Point{100,0}, 100, 50, "Stop", cb_stop}
{
            attach(timerx);
        attach(ok);
        attach(stop);
}

void window_timer::timer_go()
{
    cout << "Clock Tick" << endl;
}

void window_timer::ok_pressed()
{
    timerx.start();
}

void window_timer::stop_pressed()
{
    timerx.stop();
}

I used TimerC above to do the program bellow:




I used timer interval 0.03 and this image:

Your code has a lot of problems:
You doesn't return the control to FLTK hands using a infinite loop inside callback. So, of course, the program will be unresponsive, naturally.


.

Osman Zakir

unread,
Aug 22, 2017, 8:38:31 AM8/22/17
to PPP-public
I still can't get the image to move.   
chapter16ex7.cpp

Osman Zakir

unread,
Aug 24, 2017, 8:11:09 AM8/24/17
to PPP-public
Question: Would it be good if I derived Flying_airplane_window from window_timer as a publicly derived class and then took out the callbacks and functions called by said callbacks  out of window_timer and put them into Flying_airplane_window?  I'll have define them similarly to how you've defined them in window_timer, except that they'll have the code to move the image as well (with an if-condition checking the state of the "state" member).  What I have so far is shown in the attached .cpp file. 

Please answer my question and help me out here.  Thanks in advance.
chapter16ex7.cpp

Osman Zakir

unread,
Sep 5, 2017, 6:59:35 AM9/5/17
to PPP-public
Question: Is it possible to have the "Stop" button stop the image for as long as the user doesn't press "Start"?  And is it possible to make the "Start" button move the image as long as the user doesn't press "Stop"?  Also, is it really not possible to use a loop and still give the control back to the GUI library?  Like for example, if I were to put a loop that made the image move as long as "Stop" isn't pressed, and then invoke that function in the callback action function?  Would that allow the function to give control back to the GUI library? 
Reply all
Reply to author
Forward
0 new messages