LINUX.ORG.RU

using FLTK

 ,


1

3

Привет всем, если у кого-то имеется опыт разработки на FLTK, дайте совет пожалуйста!

Пытаюсь реализовать для «Fl_Input» функционал редактирования как в терминальной строке - стрелками вверх/вниз подгружать историю ввода. Но засада с обработкой клавиш стрелок - не получается подвесить отдельный обработчик события на «стрелки» - приходится только полностью все события клавиатуры обрабатывать в собственном цикле. Или например такой вариант:


Fl_Simple_Terminal *Tty = nullptr;
Fl_Input* Input = nullptr;

/// callback
void cb(Fl_Widget*, void*)
{
  auto key = Fl::event_key();
  if(key == FL_Up) Tty->printf( "%s\n", "UP-key" );
  else if(key == FL_Down) Tty->printf( "%s\n", "Down-key" );
  else Tty->printf( "%s\n", Input->value() );
  Input->take_focus();
  return;
}

/// MAIN
int main(int, char**)
{
  ...
  Fl::option(Fl::OPTION_ARROW_FOCUS, true);
  Tty = new Fl_Simple_Terminal(0, 0, width, tty_h);
  ...
  Input = new Fl_Input(0, tty_h, width, input_h, nullptr);
  Input->callback(cb);
  ...

В таком варианте корректно обрабатывается только одно нажатие на стрелку сразу после ввода/удаления символа в строке ввода. Два нажатия подряд не работают. Что-то надо переключить в состоянии, но что? Или может использовать другой класс для ввода строки?

Ответ (спасибо, rymis):

#include <functional>
#include <FL/Fl_Window.H>
#include <FL/Fl_Input.H>
#include <FL/Fl_Simple_Terminal.H>

Fl_Simple_Terminal *Tty = nullptr;
Fl_Input* Input = nullptr;

class History {
  public:
  void log (const char* msg){ Tty->printf( "%s\n", msg ); }
  void up  (void){ log("Up is pressed."); };
  void down(void){ log("Down is pressed."); };
  void add (const char* msg){ log(msg + 2); };
};

class MyInput : public Fl_Input {
    History hist;
public:
    template <typename...Args>
    MyInput(Args&&...args) : Fl_Input(std::forward<Args>(args)...) { }

    int handle(int ev) override {
       if (ev != FL_KEYDOWN) return Fl_Input::handle(ev);
       auto key = Fl::event_key();
       if (key == FL_Up) {
           hist.up();
           return 1;
       } else if (key == FL_Down) {
           hist.down();
           return 1;
       } else if (key == FL_Enter) {
           hist.add(value());
           value("$ ");
           return 1;
       }
       return Fl_Input::handle(ev);
    }
};

int main(int, char**) {
  int width = 500; int tty_h = 500; int inp_h = 24;
  Fl_Window *Win = new Fl_Window(width, tty_h + inp_h, "App");
  Win->begin();
  Tty = new Fl_Simple_Terminal(0, 0, width, tty_h);
  Input = new MyInput(0, tty_h - 3, width, inp_h, nullptr);
  Input->insert("$ ");
  Win->end();
  Win->resizable(Tty);
  Win->show();
  Fl::focus(Input);
  return Fl::run();
}

Такой вот бесполезный но наглядный рабочий примерчик - можно даже скомпилировать и запустить. Правда, надо отметить, что народ не слишком-то любит FLTK.



Последнее исправление: bigov (всего исправлений: 4)

Не стоит, это за него Страуструп или кто там топил. Я не сомневаюсь, что в 80е он даже был ничего, но прошло уже 40 лет, а он всё там же.

anonymous
()

вы можете создать виджет на базе исходного и в нем обрабатывать события вручную

Silerus ★★★★
()
Ответ на: комментарий от anonymous

Я не сомневаюсь, что в 80е он даже был ничего, но прошло уже 40 лет, а он всё там же.

В 80-е не то что FLTK, а софт с графическим интерфейсом еще не существовал как класс.

zloy_starper ★★★
()
Ответ на: комментарий от zloy_starper

В 80-е не то что FLTK, а софт с графическим интерфейсом еще не существовал как класс.

Ещё как существовал, месье просто не знает про Smalltalk-80 и Xerox Alto/Star.

Ну а первые лиза и макинтош с графическим интерфесом на базе вышеупомянутого пошли в массы как раз во второй половине 80х.

yoghurt ★★★★★
()
Ответ на: комментарий от yoghurt

Ещё как существовал, месье просто не знает про Smalltalk-80 и Xerox Alto/Star.

Месье на ентом Smalltalk-е пописывал кое-какие программки (хотя версию того Smalltalk я уже не припомню). Ну да, вношу поправку. Во второй половине 80-х ГПИ появились. Увидев 80-е я почему-то подумал именно про 80-й год. Тем не менее, FLTK в 80-е не было. Он появился где-то на границе 2000-х. Возможно, что его и в 90-х еще не было. Так что, если применять такие критерии, то надо бы забить на Qt, так как формально это еще более старое поделие.

zloy_starper ★★★
()
Ответ на: комментарий от Silerus

да, пожалуй идея. Хотя, чешутся руки запилить полностью свою простенькую реализацию - без внешних либ...

bigov
() автор топика
Ответ на: комментарий от bigov

По идеологии fltk, насколько я понял, на виджет можно повесить только одно событие одного вида по умолчанию. Так что если хочется что то более серьезное, придется переопределять метод отвечающий за обработку событий.

Silerus ★★★★
()
Ответ на: комментарий от zloy_starper

Месье на ентом Smalltalk-е пописывал кое-какие программки (хотя версию того Smalltalk я уже не припомню)

Преклоняю шляпу передъ олдъфагомъ!

yoghurt ★★★★★
()
class MyInput : public Fl_Input {
    History hist;
public:
    template <typename...Args>
    MyInput(Args&&...args) : Fl_Input(std::forward<Args>(args)...) {
    }

    int handle(int ev) override {
        if (ev != FL_KEYDOWN)
            return Fl_Input::handle(ev);

        auto key = Fl::event_key();

        if (key == FL_Up) {
            value(hist.up(value()));
            return 1;
        } else if (key == FL_Down) {
            value(hist.down(value()));
            return 1;
        } else if (key == FL_Enter) {
            hist.add(value());
            value("");
            return 1;
        }

        return Fl_Input::handle(ev);
    }
};

Такой виджет будет работать, если реализовать class History. Но зачем FLTK в 2018 году?

rymis ★★
()
Ответ на: Offtop от theNamelessOne
// returns true
return false;
RazrFalcon ★★★★★
()
Ответ на: Offtop от theNamelessOne

Я тоже. Отбивать начало функции комментом (его читать не обязательно) просто юзабельнее - можно просто налепить строку одинаковых сиволов. Зато в длинном листинге, для тех кто не в курсе, визуально границы функций заметнее.

bigov
() автор топика
Ответ на: комментарий от rymis

Работает, ТОЛКОВО! А чем заменить, на QT? Мне кажется так тяжелее код будет, да и по лицензиям там не так просто как с FLTK.

Мне нужна интеграция с OpenGL. Из новых попробовал «Dear ImGui» (по рекомендации Filament). Невкусно - сырой. Может я чего-то еще не знаю?

bigov
() автор топика
Ответ на: комментарий от bigov

Сложно сказать на что. Я предпочитаю Gtk, но там с C++ как-то не очень интеграция и в Windows/MacOS X не родной вид (хотя мне плевать). Для маленьких тулзов у меня есть HTTP сервер с самодельными JSON RPC биндингами и запускалкой браузера, но это не enterprise, и выложить пока руки не доходят (ну и WebGL != OpenGL).

Когда-то я следил за libui, но они так и не зарелизились. Есть прикольная nana, но я не пробовал, так как в дистрибьютивах ее нет.

rymis ★★
()
Ответ на: комментарий от gadfly

Линуксопроблемы. Ещё скажи гтк3 нет. Тебе на авр запускать?

anonymous
()
Ответ на: комментарий от anonymous

Согласен. Как-то забыл про efl, а libui не видел. Респект.

bigov
() автор топика
Ответ на: комментарий от theNamelessOne

Обожаю Лор! Всегда есть повод немного пофлудить.

bigov
() автор топика

Ответ (спасибо, rymis):

#include <functional>
#include <FL/Fl_Window.H>
#include <FL/Fl_Input.H>
#include <FL/Fl_Simple_Terminal.H>

Fl_Simple_Terminal *Tty = nullptr;
Fl_Input* Input = nullptr;

class History {
  public:
  void log (const char* msg){ Tty->printf( "%s\n", msg ); }
  void up  (void){ log("Up is pressed."); };
  void down(void){ log("Down is pressed."); };
  void add (const char* msg){ log(msg + 2); };
};

class MyInput : public Fl_Input {
    History hist;
public:
    template <typename...Args>
    MyInput(Args&&...args) : Fl_Input(std::forward<Args>(args)...) { }

    int handle(int ev) override {
       if (ev != FL_KEYDOWN) return Fl_Input::handle(ev);
       auto key = Fl::event_key();
       if (key == FL_Up) {
           hist.up();
           return 1;
       } else if (key == FL_Down) {
           hist.down();
           return 1;
       } else if (key == FL_Enter) {
           hist.add(value());
           value("$ ");
           return 1;
       }
       return Fl_Input::handle(ev);
    }
};

int main(int, char**) {
  int width = 500; int tty_h = 500; int inp_h = 24;
  Fl_Window *Win = new Fl_Window(width, tty_h + inp_h, "App");
  Win->begin();
  Tty = new Fl_Simple_Terminal(0, 0, width, tty_h);
  Input = new MyInput(0, tty_h - 3, width, inp_h, nullptr);
  Input->insert("$ ");
  Win->end();
  Win->resizable(Tty);
  Win->show();
  Fl::focus(Input);
  return Fl::run();
}

Такой вот бесполезный но наглядный рабочий примерчик - можно даже скомпилировать и запустить. Правда, надо отметить, что народ не слишком-то любит FLTK.

bigov
() автор топика
Ответ на: комментарий от gadfly

Должен. Но FLTK совсем устарел, не в смысле внешнего вида, а в смысле API. Так на C++ писали в 2000 году, но сейчас это смотриться как-то странно.

rymis ★★
()
Ответ на: комментарий от rymis

Поковырял EFL - ориентация в основном на Linux, мультиплатформенность там только на словах и свежую версию для Ms-Win быстро интегрировать в проект просто нереально. Про libui - недоделка, вряд-ли вобще зарелизится.

В процессе поисков нашел два интересных варианта -

bigov
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.