FLTK - Graficzny interfejs użytkownika

Opublikowano: 16-03-2017



Nie każda aplikacja musi posiadać graficzny interfejs, ale obsługa trybu tekstowego nie wszystkich wprawia w pozytywny nastrój.

Aplikacja ma być przede wszystkim użyteczna, jej wygląd jest na drugim miejscu. Podczas wyboru biblioteki odpowiedzialnej za "okienka" brałem pod uwagę jej rozmiar, szybkość i prostotę obsługi. W końcu nie potrzebuję całego QT czy GTK+, aby stworzyć proste okno.

FLTK, czyli Fast Light Toolkit spełnia wszystkie te wymagania. To szybka, mała i dość łatwa w obsłudze (z punktu widzenia programisty) biblioteka. Nawet jej kompilacja ze źródeł nie jest skomplikowana. Dodatkowo może zostać zlinkowana statycznie razem z programem o zamkniętym kodzie źródłowym (jest rozprowadzana na zasadach licencji GNU GPL 2 z wyjątkami zezwalającymi na takie użycie).

Biblioteka ta dostarcza kilka "skórek", jednak programy napisane z jej użyciem nie są zbyt piękne. Oto przykładowe okno aplikacji zawierającej pasek menu:

/images/logviewer-fltk-menu.png

A tutaj kod źródłowy potrzebny do utworzenia powyższego okna (całość dostępna na GitHubie):

MainWindow::MainWindow() :
    Fl_Window(400, 300)
{
    begin();

    static const Fl_Menu_Item items[] = {    // dane opisujące strukturę menu
        {"&File",   0, 0, 0, FL_SUBMENU, 0, 0, 0, 0},
        {  "E&xit", FL_COMMAND + 'q', _MenuFileExit, static_cast<void*>(this), 0, 0, 0, 0, 0},
        {  0},                               // koniec podmenu

        {0}                                  // koniec menu
    };

    fMenuBar = new Fl_Menu_Bar(0, 0, 400, 30);
    fMenuBar->menu(items);                   // utworzenie menu na podstawie danych

    fEmptyBox = new Fl_Box(0, 30, 400, 270); // tworzenie pustego pojemnika,
    resizable(fEmptyBox);                    // by móc ustawić okno jako rozszerzalne

    end();
}

W linii 2 tworzone jest okno o rozmiarze 400x300 pikseli. Wywołania funkcji begin() oraz end() definiują miejsce, w którym będziemy zezwalać na dodawanie widgetów (kontrolek) do naszego okna. Z tego powodu nie musimy wywoływać żadnej metody w stylu add(fMenuBar), aby dodać menu do okna - zostanie to zrobione za nas w momencie utworzenia obiektu (linia 14).

Szczególną uwagę przykuwają zera pojawiające się w statycznej liście elementów menu (linia 9 oraz 11). Oznaczają one odpowiednio koniec podmenu oraz koniec menu, a czym są w praktyce? Zapis ten oznacza, że wszystkie pola struktury zostaną ustawione na wartość 0, stąd FLTK będzie wiedziało, że ma zakończyć konstrukcję aktualnego podmenu czy menu. Lista ta została oznaczona jako statyczna (musi ona istnieć przez cały czas działania programu), gdyż metoda menu z linii 15 nie kopiuje jej dla siebie.

struct Fl_Menu_Item {
 const char*   text;     // label()
 ulong         shortcut_;
 Fl_Callback*  callback_;
 void*         user_data_;
 int           flags;
 uchar         labeltype_;
 uchar         labelfont_;
 uchar         labelsize_;
 uchar         labelcolor_;
};
enum { // values for flags:
 FL_MENU_INACTIVE   = 1,      // Deactivate menu item (gray out)
 FL_MENU_TOGGLE     = 2,      // Item is a checkbox toggle (shows checkbox for on/off state)
 FL_MENU_VALUE      = 4,      // The on/off state for checkbox/radio buttons (if set, state is 'on')
 FL_MENU_RADIO      = 8,      // Item is a radio button (one checkbox of many can be on)
 FL_MENU_INVISIBLE  = 0x10,   // Item will not show up (shortcut will work)
 FL_SUBMENU_POINTER = 0x20,   // Indicates user_data() is a pointer to another menu array
 FL_SUBMENU         = 0x40,   // This item is a submenu to other items
 FL_MENU_DIVIDER    = 0x80,   // Creates divider line below this item. Also ends a group of radio buttons.
 FL_MENU_HORIZONTAL = 0x100   // ??? -- reserved
};

Same pola struktury są dość jasne i nie wymagają zbędnego komentarza. Pole callback_ to wskaźnik na funkcję, która zostanie wywołana po wybraniu elementu menu. Natomiast user_data_ to wskaźnik na dane, które chcemy do tej funkcji przekazać. W przykładzie (linia 8) przekazujemy wskaźnik na daną klasę, dzięki temu funkcja może zamknąć otwarte okno.

void MainWindow::_MenuFileExit(Fl_Widget*, void *ptr) // metoda statyczna
{
    MainWindow *window = static_cast<MainWindow*>(ptr);
    window->hide();
}

Tak właśnie wygląda pierwsze okno LogViewera jakie powstało. Poniżej załączam kilka zrzutów ekranu pochodzących z witryny FLTK.

A jaka jest Twoja ulubiona biblioteka do tworzenia GUI? Podziel się swoim zdaniem w komentarzu.

/images/fltk/fltk-widgets-std.png/images/fltk/fltk-widgets-gtk.png/images/fltk/fltk-widgets-plastic.png


Pytanie lub komentarz? Zostaw wiadomość!

Powiedz proszę, czy podobał Ci się ten wpis. Chętnie podyskutuję i odpowiem na dodatkowe pytania.

Comments powered by Disqus