Gtk+, Glade3, Anjuta 編程開發小結

轉 自:http://blog.chinaunix.net/u3/100915/showart_2158659.html

 

 

開發系統:

  Ubuntu Release 9.10(Karmic)

1.Gtk+簡介

    Gtk+採用的是LGPL協議的自由軟件包,是GNU項目的一部分。它是兩大跨平臺GUI toolkit之一,另一個是QT,但是QT並不是所有的版本都是開源的,分爲開源版和商業版。 Linux流行的GNOME桌面環境採用的就是Gtk+ 開發的,Google的Linux版Chrome瀏覽器也是基於Gtk+開發的。 Gtk+提供了幾乎所有流行開發語言(如 C++,Python,C#,Java等)的綁定包,但是其native語言還是C。C也是操作系統的編寫語言,Linux,Windows都是用C編寫 出來的。

    Gtk+在Windows世界裏相當於MFC或WPF。

2.LGPL 與GPL協議

    這是Linux軟件最常使用的兩種開源協議,當然還有其它的BSD,Apache,MIT。

    GPL全稱是General Public License,Linux採用的就是GPL協議,一旦使用了含有GPL協議的代碼或類庫,本身也必需開源,這是所謂的傳染性。

    LGPL是Lesser GPL,比GPL寬鬆的協議,採用了LGPL代碼的軟件可以是閉源的。底層的類庫一般就採用LGPL協議,如Gtk+和開源版的QT。

    有意思的是,2009年很多公司並沒有遵守GPL等開源協議:

  • 微軟Windows 7的USB/DVD下載安裝工具使用了GNU的代碼,一開始並沒有開放源碼,在Open Source人士的強烈抗議之後,重新發布了該工具的開源版本。

  • 射手播放器項目公開譴責騰訊的QQ影音違反開源協議。在11月份,騰訊被 ffmpeg發現並列入恥辱版。騰訊是一家全球IT市值排名17的公司,大陸唯一一個入圍全球IT市值20強的公司。

  • 軟件自由法律中心起訴百思買集團,三星電子美國,西屋電子,JVC美國,西部數 據,臺灣合勤科技違反GPL等。

  • aMule作者要求VeryCD開源,指出VeryCD是以aMule爲基礎構 建的。

  • ”綠霸“被指責使用了OpenCV的haar分類過濾器,卻沒有遵守 OpenCV的BSD協議,在版權信息中加入BSD許可證。

3.Glade3介紹

     Glade是爲Gtk+和GNOME開發出來的UI快速開發工具,它的全稱是Glade Interface Designer。

     它包含了Button,Label,Radio等所有控件,對齊方式以及設置消息函數。Glade3文件是一個純XML描述的文件,Glade3版本 之前,據說可以直接轉成代碼.h和.c。但是Glade3已經去掉這個功能了,爲了UI設計跟代碼完全分離出來,也比較符合現代編程思想和風格。

     Glade3在Windows裏相當與Blend2,它可以設計出WPF的UI。其中Blend2也是用XML描述的,叫XAML語言或文件。

     使用Glade3的一點注意事項:

    一開始建立的Windows窗口需要使用Contaner面板裏面的一個Fixed功能先固定住,這樣再添加其它控件的時候比較方便,不會出現一個 Button覆蓋住一個Windows窗口的情況,並且無法調節其大小。如果固定住Windows窗口,點擊正中間上方的Drag and Resize就可以拖動了。

4.安裝Gtk+編程的依賴包

    // Anjuta IDE

    sudo apt-get install anjuta

    // Build tools

    sudo apt-get install autogen automake build-essential indent intltool 

    sudo apt-get install gnome-core-devel 

    sudo apt-get install pkg-config

    // Help documents
    sudo apt-get install devhelp 
    sudo apt-get install libglib2.0-doc libgtk2.0-doc 

    // Glade
    sudo apt-get install glade libglade2-dev

    // Gtk+ for C++

    sudo apt-get install libglademm-2.4-dev libgnomemm-2.6-dev intltool
    sudo apt-get install libgtkmm-2.4-doc libcairomm-1.0-doc libglib2.0-doc libgnome2-doc libsigc++-2.0-doc

5.命令行編譯與makefile
  • 測試Gtk+的編譯環境,新建一個base.c的空文檔,插入以下代碼。

      #include <gtk/gtk.h>
      int main( int argc, char *argv[] ) 
     { 
         GtkWidget *window=NULL; 
         gtk_init (&argc, &argv); 
         window = gtk_window_new (GTK_WINDOW_TOPLEVEL); 
         gtk_widget_show (window); 
         gtk_main ();
         return 0;
      }

      打開終端,進入base.c的當前文件目錄,運行下面的gcc命令:

            gcc base.c -o base `pkg-config --cflags --libs gtk+-2.0`

       則生成一個base的可執行文件,運行./base,測試運行結果,可以看見一個窗口界面。表明Gtk+開發環境配置正確。

  • 也可以將編譯、鏈接命令寫成 makefile,如下:

    CC = gcc
            all:
            $(CC) base.c -o base `pkg-config --cflags --libs gtk+-2.0`

          在終端直接運行make 命 令,就可以生產base 的可執行文件。

6.Anjuta IDE編程

  6.1 測試Anjuta的環境

     1. 新建Gtk+工程

        File → New → Project → C → Gtk+2.0

        Anjuta爲我們創建了一個包含所有文件的文件夾。

     2.打開Src文件夾,包含了 main.c和gtk_foobar.ui這兩個常要用到的文件,以及callbacks.c和callbacks.h,Makefile.am文件。

       從create_window()函數裏的代碼可以看 出,*.ui是用GtkBuilder的gtk_builder_add_from_file()來讀取的。

      builder = gtk_builder_new ();

      if (!gtk_builder_add_from_file (builder, UI_FILE, &error))
     {
          g_warning ("Couldn't load builder file: %s", error->message);
          g_error_free (error);
     }

      3. 點擊Build菜單,編譯main.c文件和prjoct文件。Build成功後,再打開Run菜單,執行Execute,生產一個名字爲Windows 的窗口。這就是默認的Gtk+窗口。

   6.2 編寫一個UI界面,含Menu,Button,Label控件,實現Button的Click事件響應。

       Menu是通過加入MenuBar控件,在小窗口的樹狀層次結 構,右鍵點擊Edit來添加子菜單。

       Button,Label是直接脫控件實現。給 Menu,Buton,Label取好名字就可以了,便於編程理解。

  6.3 添加爲名爲button_Up的Button的Click響應:

  Step 1:

    在button屬性的頁面,選Signals標籤,在 GtkButton的clicked屬性添加名爲button_Up_clicked_cb()的call back 函數,anjuta會在main.c中添加一個空函數。

  Step 2:

     在create_window()函數裏建立button和label的signal_connect連接:

    // Get label_Status object

   GObject* label_Status_obj = gtk_builder_get_object(builder, "label_Status");

    // Get button objects

    GObject* button_Up_obj = gtk_builder_get_object(builder, "button_Up");

    // Connect signals (buttons --> label)

    g_signal_connect (button_Up_obj, "clicked", G_CALLBACK(button_Up_clicked_cb), label_Status_obj);

    g_signal_connect()函數裏,將label_Status作爲user data傳遞過去。

 Step 3:

  在click函數裏處理事件:

  void

  button_Up_clicked_cb (GtkButton *self, gpointer user_data)

  {

  GtkWidget* labelForStatus = GTK_WIDGET(user_data);

  gtk_label_set_text(GTK_LABEL(labelForStatus), "Up!");

  }

至此,代碼實現已經基本完成,雷同的部分作相應的處理。

7.程序實例
   
    源碼在附錄。

8.參考文獻:
  1. 開源時代2010.01(總第十六期)
  2. Devhelp


  3. 附錄
    main.c 源碼:

/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
/*
 * main.c
 * Copyright (C) alex 2010 <[email protected]>
 *
 * gtk-foobar is free software: you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * gtk-foobar is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program. If not, see <http://www.gnu.org/licenses/>.
 */


# include < sys/ types. h>
# include < sys/ stat. h>
# include < unistd. h>
# include < string . h>
# include < stdio. h>
# include < config. h>
# include < gtk/ gtk. h>

/*
 * Standard gettext macros.
 */

# ifdef ENABLE_NLS
# include < libintl. h>
# undef _
# define _( String ) dgettext ( PACKAGE, String )
# ifdef gettext_noop
# define N_( String ) gettext_noop ( String )
# else
# define N_( String ) ( String )
# endif
# else
# define textdomain( String ) ( String )
# define gettext( String ) ( String )
# define dgettext( Domain, Message) ( Message)
# define dcgettext( Domain, Message, Type) ( Message)
# define bindtextdomain( Domain, Directory) ( Domain)
# define _( String ) ( String )
# define N_( String ) ( String )
# endif

# include "callbacks.h"

/* For testing propose use the local (not installed) ui file */
/* #define UI_FILE PACKAGE_DATA_DIR"/gtk_foobar/ui/gtk_foobar.ui" */
# define UI_FILE "src/gtk_foobar.ui"

void
button_Up_clicked_cb ( GtkButton * self, gpointer user_data) ;
void
button_Middle_clicked_cb ( GtkButton * self, gpointer user_data) ;
void
button_Bottom_clicked_cb ( GtkButton * self, gpointer user_data) ;

GtkWidget*
create_window ( void )
{
    GtkWidget * window;
    GtkBuilder * builder;
    GError* error = NULL ;

    builder = gtk_builder_new ( ) ;
    if ( ! gtk_builder_add_from_file ( builder, UI_FILE, & error ) )
    {
        g_warning ( "Couldn't load builder file: %s" , error - > message) ;
        g_error_free ( error ) ;
    }

    /* This is important */
    gtk_builder_connect_signals ( builder, NULL ) ;
    window = GTK_WIDGET ( gtk_builder_get_object ( builder, "window" ) ) ;


    // Get label_Status object

    GObject* label_Status_obj = gtk_builder_get_object( builder, "label_Status" ) ;
    
    // Get button objects

    GObject* button_Up_obj = gtk_builder_get_object( builder, "button_Up" ) ;
    GObject* button_Middle_obj = gtk_builder_get_object( builder, "button_Middle" ) ;
    GObject* button_Bottom_obj = gtk_builder_get_object( builder, "button_Bottom" ) ;
    

    // Connect signals (buttons --> label)

    g_signal_connect ( button_Up_obj, "clicked" , G_CALLBACK( button_Up_clicked_cb) , label_Status_obj) ;
    g_signal_connect ( button_Middle_obj, "clicked" , G_CALLBACK( button_Middle_clicked_cb) , label_Status_obj) ;
    g_signal_connect ( button_Bottom_obj, "clicked" , G_CALLBACK( button_Bottom_clicked_cb) , label_Status_obj) ;

    g_object_unref ( builder) ;
    
    return window;
}

int
main ( int argc, char * argv[ ] )
{
     GtkWidget * window;

# ifdef ENABLE_NLS
    bindtextdomain ( GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR) ;
    bind_textdomain_codeset ( GETTEXT_PACKAGE, "UTF-8" ) ;
    textdomain ( GETTEXT_PACKAGE) ;
# endif
    
    gtk_set_locale ( ) ;
    gtk_init ( & argc, & argv) ;

    window = create_window ( ) ;
    gtk_widget_show ( window) ;

    gtk_main ( ) ;
    return 0;
}

void
button_Up_clicked_cb ( GtkButton * self, gpointer user_data)
{
    GtkWidget* labelForStatus = GTK_WIDGET( user_data) ;
    gtk_label_set_text( GTK_LABEL( labelForStatus) , "Up!" ) ;

}

void
button_Middle_clicked_cb ( GtkButton * self, gpointer user_data)
{
    GtkWidget* labelForStatus = GTK_WIDGET( user_data) ;
    gtk_label_set_text( GTK_LABEL( labelForStatus) , "Middle!" ) ;

}

void
button_Bottom_clicked_cb ( GtkButton * self, gpointer user_data)
{
    GtkWidget* labelForStatus = GTK_WIDGET( user_data) ;
    gtk_label_set_text( GTK_LABEL( labelForStatus) , "Bottom!" ) ;

}

 

gtk_foobar.ui 源碼:

< ? xml version = "1.0" ? >
< interface>
  < requires lib= "gtk+" version = "2.16" / >
  < !-- interface-naming-policy project-wide -->
  < object class= "GtkWindow" id= "window" >
    < property name= "visible" > True< / property>
    < property name= "title" translatable= "yes" > Alex Du's Test</property>
    <property name="default_width">499</property>
    <property name="default_height">400</property>
    <signal name="destroy" handler="destroy" object="NULL"/>
    <child>
      <object class="GtkFixed" id="fixed2">
        <property name="visible">True</property>
        <child>
          <object class="GtkButton" id="button_OK">
            <property name="label">gtk-ok</property>
            <property name="width_request">95</property>
            <property name="height_request">39</property>
            <property name="visible">True</property>
            <property name="can_focus">True</property>
            <property name="receives_default">True</property>
            <property name="use_stock">True</property>
          </object>
          <packing>
            <property name="x">290</property>
            <property name="y">292</property>
          </packing>
        </child>
        <child>
          <object class="GtkLabel" id="label_Content">
            <property name="width_request">270</property>
            <property name="height_request">45</property>
            <property name="visible">True</property>
            <property name="label" translatable="yes">This is from Alex Du'
s test!< / property>
          < / object>
          < packing>
            < property name= "x" > 108< / property>
            < property name= "y" > 193< / property>
          < / packing>
        < / child>
        < child>
          < object class= "GtkButton" id= "button_Cancel" >
            < property name= "label" > gtk-cancel< / property>
            < property name= "width_request" > 96< / property>
            < property name= "height_request" > 38< / property>
            < property name= "visible" > True< / property>
            < property name= "can_focus" > True< / property>
            < property name= "receives_default" > True< / property>
            < property name= "use_stock" > True< / property>
          < / object>
          < packing>
            < property name= "x" > 396< / property>
            < property name= "y" > 293< / property>
          < / packing>
        < / child>
        < child>
          < object class= "GtkMenuBar" id= "menubar1" >
            < property name= "width_request" > 97< / property>
            < property name= "height_request" > 34< / property>
            < property name= "visible" > True< / property>
            < child>
              < object class= "GtkMenuItem" id= "menuitem1" >
                < property name= "visible" > True< / property>
                < property name= "label" translatable= "yes" > _Place< / property>
                < property name= "use_underline" > True< / property>
                < child type= "submenu" >
                  < object class= "GtkMenu" id= "menu1" >
                    < property name= "visible" > True< / property>
                    < child>
                      < object class= "GtkImageMenuItem" id= "imagemenuitem1" >
                        < property name= "label" translatable= "yes" > _Up< / property>
                        < property name= "visible" > True< / property>
                        < property name= "use_underline" > True< / property>
                        < property name= "image" > image1< / property>
                        < property name= "use_stock" > False< / property>
                      < / object>
                    < / child>
                    < child>
                      < object class= "GtkImageMenuItem" id= "imagemenuitem2" >
                        < property name= "label" translatable= "yes" > _Middle< / property>
                        < property name= "visible" > True< / property>
                        < property name= "use_underline" > True< / property>
                        < property name= "image" > image2< / property>
                        < property name= "use_stock" > False< / property>
                      < / object>
                    < / child>
                    < child>
                      < object class= "GtkImageMenuItem" id= "imagemenuitem3" >
                        < property name= "label" translatable= "yes" > _Bottom< / property>
                        < property name= "visible" > True< / property>
                        < property name= "use_underline" > True< / property>
                        < property name= "image" > image3< / property>
                        < property name= "use_stock" > False< / property>
                      < / object>
                    < / child>
                  < / object>
                < / child>
              < / object>
            < / child>
          < / object>
          < packing>
            < property name= "x" > 41< / property>
            < property name= "y" > 17< / property>
          < / packing>
        < / child>
        < child>
          < object class= "GtkButton" id= "button_Up" >
            < property name= "label" translatable= "yes" > _Up< / property>
            < property name= "width_request" > 76< / property>
            < property name= "height_request" > 41< / property>
            < property name= "visible" > True< / property>
            < property name= "can_focus" > True< / property>
            < property name= "receives_default" > True< / property>
            < property name= "use_underline" > True< / property>
            < property name= "yalign" > 0. 47999998927116394< / property>
            < signal name= "clicked" handler= "button_Up_clicked_cb" / >
          < / object>
          < packing>
            < property name= "x" > 42< / property>
            < property name= "y" > 65< / property>
          < / packing>
        < / child>
        < child>
          < object class= "GtkButton" id= "button_Middle" >
            < property name= "label" translatable= "yes" > _Middel< / property>
            < property name= "width_request" > 83< / property>
            < property name= "height_request" > 43< / property>
            < property name= "visible" > True< / property>
            < property name= "can_focus" > True< / property>
            < property name= "receives_default" > True< / property>
            < property name= "use_underline" > True< / property>
            < signal name= "clicked" handler= "button_Middle_clicked_cb" / >
          < / object>
          < packing>
            < property name= "x" > 124< / property>
            < property name= "y" > 65< / property>
          < / packing>
        < / child>
        < child>
          < object class= "GtkButton" id= "button_Bottom" >
            < property name= "label" translatable= "yes" > _Bottom< / property>
            < property name= "width_request" > 82< / property>
            < property name= "height_request" > 40< / property>
            < property name= "visible" > True< / property>
            < property name= "can_focus" > True< / property>
            < property name= "receives_default" > True< / property>
            < property name= "use_underline" > True< / property>
            < signal name= "clicked" handler= "button_Bottom_clicked_cb" / >
          < / object>
          < packing>
            < property name= "x" > 213< / property>
            < property name= "y" > 67< / property>
          < / packing>
        < / child>
        < child>
          < object class= "GtkLabel" id= "label_Status" >
            < property name= "width_request" > 109< / property>
            < property name= "height_request" > 42< / property>
            < property name= "visible" > True< / property>
          < / object>
          < packing>
            < property name= "x" > 18< / property>
            < property name= "y" > 292< / property>
          < / packing>
        < / child>
      < / object>
    < / child>
  < / object>
  < object class= "GtkImage" id= "image1" >
    < property name= "visible" > True< / property>
    < property name= "stock" > gtk-missing-image< / property>
  < / object>
  < object class= "GtkImage" id= "image2" >
    < property name= "visible" > True< / property>
    < property name= "stock" > gtk-missing-image< / property>
  < / object>
  < object class= "GtkImage" id= "image3" >
    < property name= "visible" > True< / property>
    < property name= "stock" > gtk-missing-image< / property>
  < / object>
< / interface>

 

 


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章