dirac wrote:
> First of all I have extended Fl_Button providing the following methods:
> -----------------------------------------------------------------------
> void myButton::draw() {
>   fl_draw_box(FL_BORDER_BOX, x(), y(), w(), h(), FL_BACKGROUND_COLOR);
> }
> void myButton::on() {
>   fl_rectf(x()+5, y()+5, w()-10, h()-10, 0, 0, 0);
> }
> void myButton::off() {
>   fl_rectf(x()+5, y()+5, w()-10, h()-10, FL_BACKGROUND_COLOR);
> }
> -----------------------------------------------------------------------

> [..]
> if FL_KEYDOWN case, the button is turned on calling on() method
> (off() for KEYUP)

        I think the problem is deeper, but one issue is you can't
        call drawing functions (like fl_rectf) from outside the draw() call.

        Based on the description above, it sounds like fl_rectf is
        being called from the handle() method, which will cause undefined 
behavior.

        Regarding using Fl_Button to visualize keyboard keys being up/down,
        it's tricky business if you want to have an Fl_Button to visualize
        the up/down state of particular keyboard keys, because if you depend
        on FLTK's event mechanism, the button that receives the keyboard event
        will be the button that has focus.

        Assigning shortcuts to the buttons won't get what you want,
        because the button won't follow the up/down state of the key,
        the callback is only invoked once [depending on when()].

        To do what you want, there's a lot of ways, the below might be
        one way; the technique here is to derive a custom group to parent
        the buttons, and have the group's handle() method take over
        keyup/down events, controlling the appropriate button value()
        based on the key pushed/released. It also manages invoking the
        button's callback, and forcing the correct button to take focus.

        When you compile and run, typing the q/w/e keys on the keyboard
        should make the appropriate button go up and down, and should shift
        focus correctly for each key that changes state. (No attempt was made
        to alter the default mouse clicking behavior.)

        I didn't put any emphasis on custom draw behavior for buttons
        to keep the example simple. You can make your own button class
        and make a custom draw() method that draws differently based on
        the button's value(). Just be sure all your drawing calls happen
        inside the buttons draw() method, and no where else.

        This example was tested on linux + mac, didn't check windows.

#include <stdio.h>
#include <FL/Fl.H>
#include <FL/Fl_Window.H>
#include <FL/Fl_Button.H>
//#include <FL/fl_draw.H>

// Manage a group of three buttons 'q', 'w', 'e'.
class MyButtonGroup : public Fl_Group {
    Fl_Button *butts[3];                        // example: keep track of only 
3 buttons
    static void Button_CB(Fl_Widget *w, void* data) {
        Fl_Button *b = (Fl_Button*)w;
        fprintf(stderr, "Button '%s' was %s\n", b->label(), b->value() ? 
"Pushed" : "Released");
    }
public:
    MyButtonGroup(int X,int Y,int W,int H,const char *L=0) : 
Fl_Group(X,Y,W,H,L) {
        // Create the three 'q','w','e' buttons, and keep track of their 
pointers in butts[]
        // The button's label() determines which will keyboard key invokes its 
callback
        //
        Fl_Button *b;
        int i = 0;
        b = new Fl_Button(10+0,   10, 20, 20, "q"); b->callback(Button_CB); 
butts[i++] = b;
        b = new Fl_Button(10+50,  10, 20, 20, "w"); b->callback(Button_CB); 
butts[i++] = b;
        b = new Fl_Button(10+100, 10, 20, 20, "e"); b->callback(Button_CB); 
butts[i++] = b;
        end();
    }
    int handle(int e) {
        int ret = Fl_Group::handle(e);  // assume the buttons won't handle the 
keyboard events
        switch(e) {
            case FL_FOCUS:
            case FL_UNFOCUS:
                ret = 1;                // enables receiving keyboard events
                break;
            case FL_KEYDOWN:            // keyboard key pushed
            case FL_KEYUP:              // keyboard key released
            {
                // Walk button array, trying to match button's label with the 
keyboard event.
                // If found, set that button's value() based on up/down event,
                // and invoke that button's callback()
                //
                for (int t=0; t<3; t++ ) {
                    Fl_Button *b = butts[t];
                    if ( Fl::event_key() == b->label()[0] ) {   // event 
matches button's label?
                        b->take_focus();                        // move focus 
to this button
                        b->value(e == FL_KEYDOWN ? 1 : 0);      // change the 
button's state
                        b->do_callback();                       // invoke the 
button's callback
                        ret = 1;                                // indicate we 
handled it
                    }
                }
                break;
            }
        }
        return(ret);
    }
};

int main(int argc, char *argv[]) {
    Fl_Window *win = new Fl_Window(500,200,"Example");
    new MyButtonGroup(10,10,500-10,200-10);
    win->end();
    win->show();
    return(Fl::run());
}
_______________________________________________
fltk mailing list
[email protected]
http://lists.easysw.com/mailman/listinfo/fltk

Reply via email to