Введение в GTK

  • Tutorial
На ХабраХабре наконец-то появился новый блог, посвящённый GTK. Присоединяйтесь! :-)

Привет, %username%!

В сети бытуют страшные слухи об этом фреймворке, однако серией статей о нём на ХабраХабре я попытаюсь разрушить сложившиеся стереотипы.

GTK+ — это фреймворк для создания кроссплатформенного графического интерфейса пользователя (GUI). Наряду с Qt он является одной из двух наиболее популярных на сегодняшний день библиотек для X Window System.

Изначально эта библиотека была частью графического редактора GIMP, но позже стала независимой и приобрела популярность. GTK+ — это свободное ПО, распространяемое на условиях GNU LGPL и позволяющее создавать как свободное, так и проприетарное программное обеспечение.



Как это работает


GTK+ написан на языке Си, однако несмотря на это, является объектно-ориентированным. Также можно использовать обёртки для следующих языков: Ada, C, C++, C#, D, Erlang, Fortran, GOB, Genie, Haskell, FreeBASIC, Free Pascal, Java, JavaScript, Lua, OCaml, Perl, PHP, PureBasic, Python, R, Ruby, Smalltalk, Tcl, Vala.

Внутри GTK+ состоит из двух компонентов: GTK, который содержит набор виджетов (кнопка, метка и т.д.) и GDK, который занят выводом результата на экран.

Внешний вид приложений может меняться программистом и/или пользователем. По-умолчанию приложения выглядят нативно, т.е. так же, как и другие приложение в этой системе. Кроме того, начиная с версии 3.0, можно менять внешний вид элементов с помощью CSS.

Делаем «Hello, World»


Для начала за основу возьмём вот такую заготовку:

#include <gtk/gtk.h> /* подключаем GTK+ */

/* эта функция будет выполнена первой */
int main( int argc, char *argv[])
{
        /* тут мы объявим переменные */

        /* запускаем GTK+ */
        gtk_init(&argc, &argv);

        /* тут будет код нашего приложения */

        /* передаём управление GTK+ */
        gtk_main();

        return 0;
}

Пожалуйста, не используйте одинарные комментарии (//), если как и я решили писать на Си.

Давайте для начала создадим окно нашего приложения. В GTK существует несколько типов окошек, но нам понадобится обычный GtkWindow. Вставьте в нашу заготовку следующий код:

        /* это вставьте вначале, хотя на самом деле порядок не так важен */
        GtkWidget *window;

        /* ... */

        /* создать новый виджет - окно */
        window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
        /* дать окну заголовок */
        gtk_window_set_title(GTK_WINDOW(window), "Введение в GTK");
        /* установить внутренние границы (читайте ниже) */
        gtk_container_set_border_width (GTK_CONTAINER(window), 50);

Прежде чем продолжить, несколько слов об упаковке.

В GTK+ виджеты принято размещать не по координатам, а упаковывать в специальные контейнеры. Окно, которое мы создали, также является контейнером, который может содержать только один виджет. Нам этого хватит, но в ином случае нам бы пришлось добавить специальный виджет-контейнер, который может представлять из себя сетку, а также горизонтальные или вертикальные поля. Но об этом я подробнее расскажу в следующем топике.

Пока остановимся на окне. Напомню, что окно — это контейнер, которому мы указали толщину границ в 50 пикселей. Что это значит?



Это значит, что мы создаём своего рода невидимую рамку вокруг этого контейнера и по этому ничего не сможем разместить в этой области.

Теперь рассмотрим сигналы.

Мы можем связать определённое событие, которое должно произойти с виджетом, со своей функцией.

        /* когда пользователь закроет окно, то выйти из приложения */
        g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL);

В данном случае это стандартная фунция gtk_main_quit(), которая безопасно завершит наше приложение.

Теперь создадим кнопку, по нажатию на которую будет появляться окошко с надписью «И тебе привет, %username%!».

Кнопка (GtkButton) — это тоже контейнер, который также может содержать один виджет. Чтобы не усложнять код созданием метки и помещением её в кнопку, сделаем вот так:

        /* это вставьте вначале, хотя на самом деле порядок не так важен */
        GtkWidget *button;

        /* ... */

        /* создать кнопку с меткой */
        button = gtk_button_new_with_label("Привет, ХабраХабр!");
        /* упаковать нашу кнопку в окно */
        gtk_container_add(GTK_CONTAINER(window), button);

        /* когда пользователь кликнет по ней, то вызвать ф-цию welcome */
        g_signal_connect(GTK_BUTTON(button), "clicked", G_CALLBACK(welcome), NULL);

Выглядеть это будет так:



Теперь реализация функции welcome:

/* выводит приветствие */
void welcome (GtkButton *button, gpointer data)
{
        /* виджеты */
        GtkWidget *dialog;
        GtkWidget *label;
        GtkWidget *content_area;

        /* создать диалог */
        dialog = gtk_dialog_new_with_buttons("Ошибка LOL!!!111",
                                             NULL,
                                             GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
                                             GTK_STOCK_OK,
                                             GTK_RESPONSE_ACCEPT,
                                             NULL);

        /* получить контейнер, в который будем пихать метку */
        content_area = gtk_dialog_get_content_area(GTK_DIALOG(dialog));

        /* сама метка */
        label = gtk_label_new("\n\nИ тебе привет, %username!%");
        gtk_container_add(GTK_CONTAINER(content_area), label);
        gtk_widget_show(label);

        /* запускаем диалог */
        gtk_dialog_run(GTK_DIALOG(dialog));
        /* а потом прячем */
        gtk_widget_destroy(dialog);
}


Результат после нажатия:



Вот так просто и быстро мы создали рабочую программу. В следующих топиках я расскажу про использование Glade (программа, чтобы рисовать виджеты без кода) и создание собственных виджетов.

Компиляция


gcc file_name.c -o file_name `pkg-config --cflags --libs gtk+-3.0`

Не забудьте установить пакет GTK для разработчика (кончается на "-dev").

Что-нибудь ещё?


Да, пожалуй, приведу несколько ссылок:

www.gtk.org — официальный сайт

www.gtkforums.com — англоязычный форум, посвящённый GTK

developer.gnome.org — информация для разработчиков под среду GNOME. Содержит много полезной информации о GTK, в том числе и на русском языке.

UPD: Полный код примера на PasteBin — pastebin.com/iPttWBne
Поделиться публикацией
AdBlock похитил этот баннер, но баннеры не зубы — отрастут

Подробнее
Реклама
Комментарии 68
  • +1
    было бы интересно какой-нить толстый гайд по созданию/редактированию .gtkrc-шных тем.
    • 0
      В стандартной документации есть. Если будет время, то переведу.
      Однако в любом случае переходите на CSS.
      • +5
        гм. неужто раздел про ресурсы .gtkrc переписали с «если вы девелопер, то сами разберетесь. а если юзер — сосите писос» на что-то адекватное?
        • +1
          Вроде да, только ищите документацию по GTK 2, т.к. в третей версии могли убрать это.
    • 0
      На первый взгляд ну оочень похоже на Qt. Даже сигналы и слоты есть.
      • 0
        Если захотите использовать GTK (и вы ранее работали, как я понимаю, с Qt) то советую Gtkmm — оболочку для C++.
        • 0
          Спасибо за совет, обязательно опробую в скором времени.
        • 0
          Работают они немного по разному, насколько я понял.
          • 0
            Идея похожая, а реализация, конечно, разная.
          • 0
            Да, и не только в Qt и GTK взяты такие модели обработки событий. Возьмите wxWidgets, например.
          • +3
            Насчет комментариев не понял. Кто-нибудь просветит?
            • +2
              В официальной документации советуют не использовать комментарии в стиле C++ (//), т.к. могут быть проблемы на некоторых компиляторах.
              Это относится, стати, не только GTK, но и ко всем программам на чистом Си.
              • +3
                В С89 отсутствуют одинарные комментарии. В C99 они присутствуют.

                Я бы не стал особо заморачиваться поддержкой C89; согласно этому стандарту, переменные можно объявлять только в начале блока и нельзя объявлять переменную внутри конструкции for. Большинство современных компиляторов основные особенности C99 отлично переваривают.
            • +2
              Кстати, а как у него с компиляцией под Win?
              • 0
                Со старыми версиями все нормально. Начиная с 3.0 есть некие проблемы — см. мой вопрос ниже.
              • 0
                Что-нибудь известно по портированию GTK 3 на Windows и OSX? Когда я проверял последний раз, желающих портировать под Windows не было вообще, под OSX один энтузиаст неторопливо копал на основе jhbuild, но у него 10.5, апгрейдиться не собирается, и начинаю с 10.6 сборка, понятное дело, не работает :(.
                • 0
                  • 0
                    За windows ссылку спасибо, про openSUSE билды слышал, но где точно лежат не видел.
                    А вот про MacOS — это пост более чем годовалой давности, с тех пор ничего не изменилось насколько я вижу, месяц назад ни на 10.6, ни на 10.7 собрать не смог :(.
                    • 0
                      Будет время, посмотрю на своём MacBook.
                  • +2
                    На счёт OS X — в макпортах есть:

                    $ port search gtk | grep gtk3
                    gtk3 @3.0.5 (gnome, x11)
                  • 0
                    Хотелось бы скачать весь исходник файлом.
                  • 0
                    О, спасибо, хороший блог!
                    Для начинающих с GTK в C++ — лучше использовать gtkmm, не знаю как сейчас, но ранее (3-4 года назад где-то) — использовать сишный чистый gtk в программах с классами — намучился, определял, где нужно после передачи по указателю разрушать объект, где нет… документация была не на самом высоком уровне, так что приходилось экспериментировать.
                    В общем, если пишете на C++ лучше сразу использовать gtkmm, в своё время кучу кода переписывал из-за того, что посчитал проще пользоваться чистым gtk.
                    ps
                    Будет время, может, накатаю пару статей про использование pango\cairomm, да и остальные библиотеки в связи с gtk (скажем, opengl).
                    • 0
                      Давай, я сейчас тоже пишу очередной топик. Опубликую через пару дней, чтоб не всё сразу.
                      А то я боялся, что в новый блог никто кроме меня писать не будет :-)
                      • –1
                        Тоесть, то, что названо «обёрткой для C++» — именно обёртка (а внутри весь ужас наследования через указатели первым полем)?
                        • 0
                          Не знаю что внутри, но это именно обёртка.
                      • +3
                        Хочу спросить, есть ли где-то описание/пример создания не окошка с 3 кнопками, а сколько-нибудь серьезного приложения, с таблицами, лейаутами и формами?

                        У меня есть подозрение, что этот GTK — тяжелая, медленная, плохо работающая под Windows, неэффективно взаимодействующая с графичским сервером, неудобная для разработчика библиотека. К тому же она написана в странной манере, на одних функциях.
                        • +2
                          Это как раз те стереотипы, о которых я писал вначале топика. Для серьёзных приложений нужно наследовать класс GtkApplication и плясать от него. Я планирую написать целую серию уроков в этом блоге.
                          • +1
                            С каким графическим сервером и на какой OS оно неэффектино взаимодействует? С X11 на Windows?
                            • +1
                              Некоторые старые приложения в самом деле почему-то притормаживают в Windows.
                              • +4
                                Чудес не быват. Вомзожно, они что-то делают неправильно, и это не относится к графическому тулкиту. GIMP, Inkscape и Pidgin не тормозят — что еще от GTK надо? :)
                            • +2
                              Довелось работать с GTK и с Qt. GTK конечно не такой плохой, как вы его описали, но желания к нему возвращаться у меня нет никакого. Qt мне понравился намного больше. В Qt есть чёткая структура, а в gtk просто зоопарк каких-то функций, причём порой приходится через каждую минуту лезть в документацию, чтобы понять что к чему. К тому же Qt прекрасно работает под windows, да и вообще кроссплатформенность это главный козырь Qt, чего не скажешь про gtk. Плюс, у Qt документация лучше. Возможно когда-нибудь его допилят, а пока, если хотите изучать gtk, советую сначала посмотреть в сторону Qt.
                              • +2
                                Капитан Очевидность подсказывает что GTK+ также является кроссплатформенным и прекрасно работает и под Windows и под Mac OS: www.gtk.org/screenshots/
                                • +3
                                  Насчет прекрасно я бы не совсем согласился. Все-таки, в отличие от Qt, GTK изначально не позиционировался как кроссплатформенный тулкит. Да, впоследствии он стал очень успешным и был портирован под OSX и Windows — но энтузиастами, по остаточному признаку. Как следствие — неродной вид интерфейса (Qt, между прочим, тоже рисует виджеты самостоятельно — но при это найти отличия от родного интерфейса очень трудно), сильное запаздывание новых версий (GTK3 в данный момент нормально работает только под *NIX, то же можно сказать про GObject Introspection — а технология довольно перспективная), баги вида «ничего не работает», которые не чинят годами (например, если окно GEdit под OSX попытаться поресайзить — он упадет. Известный баг GTK, но никто не чинит потому что нет энтузиастов возиться с «ненужными» OSX и Windows).
                            • +1
                              Написание комментариев в стиле /* коммент */ — это зло! Любые многострочные комментарии должны использоваться только во время отладки отдельным программистом. Самое банальное — я хочу переписать чью-то функцию, и комментирую её /* void some_func()… */, это заставляет лезть и выискивать все встроенные /*комментарии*/, тратить время.
                              • 0
                                Не понял, зачем вам искать все встроенные комментарии?
                                • 0
                                  Извините, это наболевшее командной работы, когда нужно всё срочно, а приходится на таких мелочах тратить минуту-две выискивая эти комментарии.
                                  • +1
                                    А, понял о чём вы. Смутило слово «встроенные», я бы назвал их внутренними. Но с основным вашим тезисом не согласен — для отладки/тестирования/рефакторинга лучше использовать // (как раз из-за однозначности и легкости отмены), а для документирования /* */, которые со временными // не конфликтуют. Плюс /* */ любой компилятор съест, а не только тот, который вы используете для отладки, более переносимый способ для постоянных комментов.

                                    Хотя, дело вкуса и соглашений проекта. Если, конечно, вы не блокноте работаете, и закомментировать блок в // много сложне чем в /* */ :)
                                • 0
                                  Нормальные комментарии появились только в C++ и хотя многие компиляторы уже принимают и их в коде, по-прежнему есть компиляторы, которые будут выдавать ошибку. По этому, если пишете на Си, то используйте комментарии вида /* */, а если на С++, то можете использовать и то, и то.
                                  • 0
                                    Это что-то очень экзотическое, где не понимаются однострочные // в С.
                                  • +5
                                    #if 0
                                    void f()
                                    ...
                                    #endif
                                    • 0
                                      +1. Но не во всех редакторах такое комментирование переключает подсветку. Когда пишешь одновременно и на плюсах и на скриптовых языках, не сразу вспоминаешь про то, что можно воспользоваться препроцессором.
                                      • 0
                                        В нормальных редакторах есть функция которая (рас)комментирует блок, корректно обрабатывая внутренние комментарии.
                                        • 0
                                          когда я дома налегке пишу или в офисе неспеша — это одно. А когда срочно-срочно надо что-то пофиксить, а тем более удаленно — это другое. И вот в таких моментах. когда удалённо, начинаешь испытывать большую нелюбовь к многострочным комментариям.
                                          Особенно на этом шишек набил, когда на производстве сидишь возле большого станка, срочно фиксишь что-то, а у тебя из имеющегося только простенький ноутбук с mc.
                                          • +1
                                            Давным давно прошли те времена, когда расшифрока Emacs = Eight Megabytes And Constantly Swapping была актуальна.
                                            • –1
                                              а осадок остался © анекдот
                                    • 0
                                      Про #if 0 / #endif не слышал? Рикаминдую.
                                    • +2
                                      Спасибо, жду продолжения.
                                      • 0
                                        2012-й год. 17 лет после изобретения Delphi. Рисуем GUI ручками…
                                        Надеюсь, для GTK+ есть удобный кроссплатформенный интегрированный редактор GUI. Иначе, для чего всё это?
                                        • 0
                                          Конечно есть, это же статья для новичков. Позже будет и про редактор и про специальную среду разработки.
                                          • 0
                                            Есть glade, в котором можно набросать сложную формочку (да еще и с поддержкой gettext). Но некоторые формы удобнее создавать вручную.
                                            • 0
                                              Как правило, главная форма приложения создаётся вручную, а диалоги с настройками и т.д. в Glade. Такова традиция :-)
                                              • 0
                                                Смотря что там за форма. Мне удобнее было главное окно (с кучей менюшек и т.п.) сделать в glade, а также вспомогательные окна; всякую мелочевку (простенькие диалоги настройки, диалог открытия файла и т.п.) же я делал вручную.
                                                • +1
                                                  В своё время долго копался в исходниках GNOME'овских программ, там везде, насколько я помню, диалоги лепятся в Glade, а главное окошко в коде. Ваша проблема, наверное, в том, что вы пытались делать тулбары и менюшки в коде, но это не true. Поищите в документации GtkUIManager — это как раз то, что вам нужно.
                                                  • 0
                                                    Я с GTK долго возился, но на форумах направили на путь истинный. Подсказали даже, как внедрять glade'овский код в приложение.
                                                    Еще бы с gettext'ом так же…
                                                    • 0
                                                      GtkUIManager не есть Glade. Это тоже XML, но в несколько ином виде. Как я уже писал выше, используй их оба и будет тебе счастье.
                                          • 0
                                            Пользуясь случаем, хочу передать привет задать вопрос специалистам по GTK. Вот такие комбобоксы — это разрабы Wireshark'а поленились пару пропертей выставить, или GTK по-другому не умеет (или не умел — скриншот старый)?
                                            • +1
                                              Сейчас проверил на последней версии (GTK 3.2). Комбобокс уходит вверх до конца экрана, но вниз не идёт. Наверное, это фича, а не баг.
                                              • 0
                                                Это фича GTK+. При раскрытии список комбобокса позиционируется так, чтобы выделенный элемент оставался под курсором.
                                                • 0
                                                  Но ведь при этом можно не рисовать его пустым до низа экрана? И сверху тоже как-то ограничивать, добавляя скроллбар, а не эти кнопки-стрелочки ужасные сверху и снизу?
                                                  • +1
                                                    Доподлинно не известно, но думаю, с этим не заморачиваются потому, что такие комбобоксы противоречат Gnome HIG. В списке должно быть от трёх до приблизительно десяти элементов.

                                                    В крайнем случае, если очень хочется сделать таки комбобокс — можно сделать его многоколоночным.
                                                    • 0
                                                      Ясно, спасибо.
                                              • 0
                                                Я не училсяся на программистов, но по роду деятельности иногда нужно писать простые приложения с графическим интерфейсом для настройки чего либо. Из последнего опыта, две программы для iPhone и одна на QT под линукс.
                                                Акцентирую еще раз внимание, что я не программист, но начиная изучение c++ и qt с нуля, уже через месяц я написал нужную мне программу, на Айфоне я это сдела уже за несколько дней.
                                                Но посмотрев как программировать на gtk, мне кажется тут с ума сойдешь изучать все эти функции, библиотека совершенно не само документирована, это очень усложняет и замедляет разработку.
                                                • 0
                                                  Вы не хотите продолжить курс лекций? Дело в том, что в рунете нет уроков по GTK. Единственное, что удалось найти — это ваши уроки. Хотелось бы продолжить изучение GTK.
                                                  • 0
                                                    Честно говоря, эта статья писалась только для того, чтобы заполнить пустой хаб «GTK+» на Хабре. Планов продолжать у меня не было.

                                                    Если вы хотите разобраться в GTK, то, я считаю, главное понять как в нем реализовано ООП (если вы пишете на C++ и gtkmm, то этот пункт для вас не актуален) и идею с контейнерами и виджетами (хотя, опять же, можно класть все в GtkFixed, но лучше так не делать). Дальше просто открываете документацию и изучаете, какие в GTK есть классы.

                                                    Также вам стоит посетить "Центр разработки GNOME", где собраны все актуальные примеры и руководства.
                                                  • 0
                                                    Прекрасно.

                                                    Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.