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