FLTK: подкласс Fl_Value_Input не получает события FL_KEYDOWN (только FL_KEYUP)

Я создал подкласс FL_Value_Input таким образом, чтобы я мог задать виджету цвет при его изменении, но пользователь еще не нажал клавишу ввода.

Глупость заключается в том, что функция handle(int e) никогда не вызывается, если событие является событием FL_KEYDOWN, другие события (такие как FL_KEYUP, FL_DRAG, FL_FOCUS и т. д.) распространяются нормально.

Виджет является частью иерархии виджетов... Может быть, один из его родителей в этой иерархии поглощает это конкретное событие FL_KEYDOWN?

РЕДАКТИРОВАТЬ: по-видимому, виджет также не имеет фокуса (проверено путем сравнения this с Fl::focus()), что странно, поскольку я ввожу его.

Любая помощь будет оценена по достоинству.

Fx_Value_Input::Fx_Value_Input(int x, int y, int w, int h, const char* l)
: Fl_Value_Input(x, y, w, h, l)
{}

int Fx_Value_Input::handle(int e)
{
    int r = Fl_Value_Input::handle(e);

    if (e == FL_KEYBOARD)
    {
            if ((Fl::event_key() != FL_Enter && Fl::event_key() != FL_KP_Enter ) )
                    color(Fx::get_modified_color());
            else if ((Fl::event_key() == FL_Enter || Fl::event_key() == FL_KP_Enter) &&             color() == Fx::get_modified_color())
                    color(FL_WHITE);
            redraw();
        }

    return r;
}

person Ben    schedule 27.10.2016    source источник
comment
Хм, получается, что Fl_Value_Input не является Fl_Input, а содержит Fl_Input в качестве члена (инкапсуляция). Этот конкретный член получает и обрабатывает событие FL_KEYDOWN и имеет фокус... Мне нужно найти способ, которым он распространяет FL_KEYDOWN на Fl_Value_Input...   -  person Ben    schedule 28.10.2016


Ответы (2)


Использование FL_KEYDOWN - это способ работы Windows, который, как вы обнаружили, не работает, потому что вам нужно создать подкласс Fl_Input_: не Fl_Input, и даже в этом случае он не работает должным образом.

Вместо этого используйте when(FL_WHEN_CHANGED|FL_WHEN_ENTER_KEY). Проверяйте change() при нажатии клавиш и clear_changed(). Он не устанавливается при нажатии клавиши ввода. Вы можете изменить цвета обратно, когда это условие будет выполнено.

inputkey = new Fl_Input...
inputkey->when(FL_WHEN_CHANGED| FL_WHEN_ENTER_KEY);
inputkey->callback(cb);
....

void cb(Fl_Widget *ob)
{
   Fl_Input* ip = dynamic_cast<Fl_Input*>(ob);
   if (ip->changed())
   {
       // change colour
       ip->clear_changed();
   }
   else
   {
      // change colour
   }
}
person cup    schedule 28.10.2016

Получил ответ в группе Google FLTK с объяснением проблемы... Для этого нет простого обходного пути...

FLTK доставляет нажатия клавиш непосредственно в виджет фокуса. Fl_Value_Input включает виджет Fl_Input, и этот виджет становится виджетом фокуса, когда вы щелкаете в поле ввода.

Следовательно, «родительский» Fl_Value_Input никогда не видит события Fl_KEYDOWN. Обратите внимание, что я процитировал «родительский», потому что Fl_Value_Input — это очень особый случай. Он не является производным от Fl_Group, но ведет себя как виджет Fl_Group.

Так почему же ваш производный виджет получает события FL_KEYUP? Это еще одна особенность FLTK: события FL_KEYUP также доставляются в виджет фокуса в первую очередь. Однако, AFAICT, ни один основной виджет FLTK не обрабатывает события FL_KEYUP — все они возвращают 0 в своих методах handle(). Если виджет фокуса не обрабатывает событие, FLTK пытается доставить его родительскому виджету, а затем вверх по иерархии виджетов, пока не достигнет окна верхнего уровня. Следовательно (и это странно IMHO), в конечном итоге все виджеты будут получать все события FL_KEYUP, если только один виджет не вернет 1 из своего метода handle() (что обычно не так). В зависимости от глубины виджета фокуса в общей иерархии виджетов может случиться так, что некоторые виджеты получат одно и то же событие FL_KEYUP несколько раз, потому что все родительские группы виджета фокуса пытаются доставить событие всем своим дочерним элементам.

person Ben    schedule 28.10.2016