Search code examples
c++clrfltk

How can I get the value of a widget the exact moment a button is clicked FLTK


The goal is to be able to get the value of a widget such as FL_Input when I click my button.

One way I could do this is by using events and classes. Such as

#include <FL/Fl.H>
#include <FL/Fl_Window.H>
#include <FL/Fl_Button.H>
#include <iostream>
using namespace std;

class MyButton : public Fl_Button
{
    static int count;
public:
    MyButton(int x, int y, int w, int h, const char*l = 0)
        :Fl_Button(x, y, w, h, l) {}

    int handle(int e)
    {
        int ret = Fl_Button::handle(e);
        //test - - - cout << endl << count++ << " ******** button " << label() << " receives ";


        switch (e)
        {
        case FL_PUSH:
            trigger..
            break;


        }
        return(ret);
    }

};

int MyButton::count = 0;

void but_a_cb(Fl_Widget* w, void* v) {
    cout << endl << "Button A callback!" << endl;
}


int main()
{
    Fl_Window win(120, 150);
    win.begin();

    MyButton but_a(10, 10, 100, 25, "A");
    but_a.shortcut('a');
    but_a.callback(but_a_cb);


    win.end();
    win.show();
    return(Fl::run());
}

However, this is not an optimal way of doing this for me because I want to take multiple inputs and put them in a vector and use them in this. To do this i am thinking of an input callback that will return the input value and I would use a "Fl_Input->when(FL_CHANGED)"

Preferably I would be able to get the values and put them into a vector on button click by using code in the main function and not the button because this would require me to rework my program to implement this.

Just declaring the vector in the main doesn't work due to it taking the value on form load.

Summarising, I want to know how I can create something like an if statement that is triggered when a button is clicked to get values of fl_inputs at the moment when the button is clicked. T

Note I am going to implement this with a database so that I will need it to work with CLR

Extra code I have came up with

void done_cb(Fl_Widget* w, void* param)
{
    Fl_Input* i = (Fl_Input*)param;
    string inputstring = i->value();
    cout << inputstring;

    // What i tried for the vectors
    //vector<Fl_Input*> v = *reinterpret_cast<vector<Fl_Input*> *>(param);
    //string inputstring = v[0]->value();
    //cout << inputstring;
    
}
void signupScreen (void) {

    Fl::event_dispatch(myHandler);
    

    Fl_Window *window = new Fl_Window(200, 150);
    window->begin();
    int x = 50, y = 10, w = 100, h = 30;

    y += 35;
    

    y += 35;
    Fl_Input *input2 = new Fl_Input(x, 10, w, h, "str");
    
    Fl_Button* done = new Fl_Button(x, y, 100, h, "Done");
    done->when(FL_WHEN_CHANGED);
    
    string strinput;

    //strinput = input2->value();
    
    //input2->when(FL_WHEN_CHANGED);

        
    //std::vector<Fl_Input*> v = { input2 };
    done->callback(done_cb, input2);

    

    cout << strinput;
    
    window->end();
    

    window->show();
    
}



Solution

  • You may define a new class derivated from Fl_Input which has a member of type std::vector<std::string> where you store the text written in your input field.

    #ifndef __MYINPUT_H
    #define __MYINPUT_H
    #include <FL/Fl_Window.H>
    #include <FL/Fl.H>
    #include <FL/Fl_Input.H>
    #include <iostream> 
    #include <vector>
    
    
    class myinput: public Fl_Input
    {    
        public:
            /* 
            Instead of setting it public, you may create get and set methods.
            */
            std::vector<std::string> _storing;
            // Constructor 
            myinput(int x, int y, int h, int l, std::vector<std::string> S, const char* ll = 0);
            ~myinput(){};
            
    };
    
    #endif
    

    The .ccp file:

    #include <myinput.hpp>
    
    myinput::myinput(int x, int y, int h, int l,std::vector<std::string> S,const char* ll):Fl_Input(x, y, h,l,ll)
    {
        _storing = S;
    }
    

    Then, you may use it as shown below:

    #include <FL/Fl.H>
    #include <FL/Fl_Window.H>
    #include <myinput.hpp>
    #include <FL/Fl_Button.H>
    
    void add_cb(Fl_Widget* w, void* p){
        myinput* i = (myinput*)p;
        std::string inputstring = i->value();
        i->_storing.push_back(inputstring);
    
        // Just to show that it is working
        std::cout<< "Updated string:" << std::endl;
        for (int j=0; j<i->_storing.size(); j++ )
            std::cout << i->_storing[j] << std::endl;
    }
     
    int main(int argc, char **argv) {
    
        Fl_Window *G_win = 0;
        G_win = new Fl_Window(300,300,"Test");
    
        myinput* A;
        // Where you may store the strings
        std::vector<std::string> mytext;
    
        A = new myinput(100,50,100,20, mytext,"Insert text");
    
        Fl_Button* add;
    
        add = new Fl_Button(250,50,25,25,"+");
        add->callback(add_cb,A);
    
    
        G_win->end();
        G_win->show(argc, argv);
        
        return Fl::run();
    }
    

    If you want to store the strings coming from several input fields, you may collect the Fl_input inside a Fl_Group and pass the latter to the button's callback.

    Please note that the code that I wrote is not very elegant nor it is the most efficient: it was just to show you my idea to solve your problem (if I understood it correctly).