GTK入門


環境准備

官網下載 GTK 源碼包,因為本機 GLib 版本不夠,下載一個非最新版的 GTK3.8.0 先學習用

直接閱讀 "/gtk+-3.8.0/docs/reference/gtk/html/gtk-building.html" 進行操作

安裝完畢,gtk3-demo 出來 gtk 的樣例界面即安裝搞定

實例學習

編譯命令和編譯腳本

編譯參數包括 pkg-config --libs --cflags gtk+-3.0

為了方便,用腳本管理起來

build.sh

#!/bin/bash
if [ $# -lt 1 ]; then
    echo "usage: $0 [xxxx.c]"
    exit
fi
 
gcc -o $1_out $1 `pkg-config --libs --cflags gtk+-3.0`

一個簡單的HelloWorld按鈕

01_simple_button.c

#include <gtk/gtk.h>

// 回調函數1
void hello( GtkWidget *widget, GdkEvent *event, gpointer data )
{
    g_print("Hello World\n");
}

// 回調函數2
void destroy( GtkWidget *widget, gpointer data )
{
    gtk_main_quit();
}

gint delete_event( GtkWidget *widget, GdkEvent *event, gpointer data )
{
    /**
     * 如果 "delete_event" 信號處理函數
     * 返回 FALSE,GTK 會發出 "destroy" 信號
     * 返回 TRUE,你不希望關閉窗口
     * 當希望彈出 "你確定要退出嗎?" 對話框時可以用到
     */
    g_print("delete event occurred\n");

    return FALSE;
}

int main( int argc, char *argv[] )
{
    // GtkWidget 是構件的存儲類型
    GtkWidget *window;
    GtkWidget *button;

    /**
     * gtk_init 函數在所有的 GTK 程序都要調用
     * 參數由命令行中解析出並填充進來
     */
    gtk_init( &argc, &argv );

    window = gtk_window_new( GTK_WINDOW_TOPLEVEL );

    /**
     * 當窗口收到 "delete_event" 信號(該信號由窗口管理器發出,
     * 通常是"關閉"選項或是標題欄上的關閉按鈕發出的)
     * 我們讓其調用在前面定義的 delete_event 函數
     * 傳給回調函數的 data 參數值是 NULL,它會被回調函數忽略
     */
    g_signal_connect( G_OBJECT( window ), "delete_event",
        G_CALLBACK( delete_event ), NULL );

    /**
     * 連接 "destroy" 事件到一個信號處理函數,對該窗口調用
     * gtk_widget_destroy 函數或在 "delete_event" 回調函數
     * 中返回 FALSE 值都會觸發該事件
     */
    g_signal_connect( G_OBJECT( window ), "destroy",
        G_CALLBACK( destroy ), NULL );

    // 設置窗口邊框的寬度
    gtk_container_set_border_width ( GTK_CONTAINER(window), 10 );
    // 創建一個標簽為 Hello World 的新按鈕
    button = gtk_button_new_with_label( "Hello World" );

    // 當按鈕觸發 "clicked" 事件時,會調用回調函數 hello
    g_signal_connect( G_OBJECT( button ), "clicked",
        G_CALLBACK( hello ), "1" );

    // 當按鈕觸發 "clicked" 事件時,調用 gtk_widget_destroy(window)
    // 來關閉窗口,"destroy" 信號會從這里或從窗口管理器發出
    // g_signal_connect_swapped (G_OBJECT (button), "clicked",
    //     G_CALLBACK (gtk_widget_destroy),window);
    
    // 把按鈕放入窗口(一個gtk容器)中
    gtk_container_add ( GTK_CONTAINER( window), button );
    
    // 顯示新創建的按鈕和窗口
    gtk_widget_show( button );
    gtk_widget_show( window );

    // 程序運行停在這里等待事件的發生(如鍵盤事件/鼠標事件)
    gtk_main();

    return 0;
}

兩個按鈕

02_two_buttons.c

#include <gtk/gtk.h>

// 改進回調函數,傳遞到該函數的數據將打印到標准輸出中(stdout)
void callback( GtkWidget *widget, gpointer data )
{
    g_print( "%s", (gchar *) data );
}

// 回調函數2
gint delete_event( GtkWidget *widget, GdkEvent *event, gpointer data )
{
    gtk_main_quit();
    return FALSE;
}

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

    gtk_init( &argc, &argv );
    window = gtk_window_new( GTK_WINDOW_TOPLEVEL );
    
    // 設置窗口標題
    gtk_window_set_title( GTK_WINDOW( window ), "Hello Buttons!" );

    g_signal_connect( G_OBJECT( window ), "delete_event",
        G_CALLBACK( delete_event ), NULL );

    gtk_container_set_border_width( GTK_CONTAINER( window ), 20 );

    // 創建一個組裝盒,組裝盒非可見,它僅被作為排列構件的工具
    box1 = gtk_hbox_new( FALSE, 1 );
    // 把組裝盒放入主窗口中
    gtk_container_add ( GTK_CONTAINER( window ), box1 );
    
    button = gtk_button_new_with_label( "Hello" );
    g_signal_connect( G_OBJECT( button ), "clicked", G_CALLBACK(callback), "hello");
    
    // 代替 gtk_container_add, 把按鈕放入組裝盒中, 組裝盒已經放入窗口中了
    gtk_box_pack_start( GTK_BOX( box1 ), button, TRUE, TRUE, 0 );
    gtk_widget_show( button );

    button = gtk_button_new_with_label( "World" );
    g_signal_connect( G_OBJECT( button ), "clicked", G_CALLBACK(callback), "World");
    gtk_box_pack_start( GTK_BOX( box1 ), button, TRUE, TRUE, 0 );
    gtk_widget_show( button );

    button = gtk_button_new_with_label( "!" );
    g_signal_connect( G_OBJECT( button ), "clicked", G_CALLBACK(callback), "!");
    gtk_box_pack_start( GTK_BOX( box1 ), button, TRUE, TRUE, 0 );
    gtk_widget_show( button );

    gtk_widget_show( box1 );
    gtk_widget_show( window );
    
    gtk_main();

    return 0;
}

一圖片和一按鈕

03_image_and_button.c

#include "gtk/gtk.h"

int main( int argc, char *argv[] )
{
    GtkWidget* window;
    GtkWidget* vbox;
    GtkWidget* image;
    GtkWidget* button;
  
    gtk_init( &argc, &argv );
  
    window = gtk_window_new( GTK_WINDOW_POPUP );
    gtk_window_set_title( GTK_WINDOW(window), "Splash窗口" );
    g_signal_connect( G_OBJECT(window), "destroy", G_CALLBACK( gtk_main_quit ), NULL );
    
    // 設置窗口處於屏幕中央
    gtk_window_set_position( GTK_WINDOW( window ), GTK_WIN_POS_CENTER );
    // gtk_container_set_border_width( GTK_CONTAINER(window), 20 );
  
    vbox = gtk_vbox_new(FALSE, 0);
    gtk_container_add( GTK_CONTAINER(window), vbox );
    
    image = gtk_image_new_from_file("gnome-desktop.png");
    gtk_box_pack_start( GTK_BOX(vbox), image, FALSE, FALSE, 0 );
  
    button = gtk_button_new_with_label( "Splash窗口" );
    g_signal_connect( G_OBJECT( button ), "clicked", G_CALLBACK( gtk_main_quit ), NULL );
  
    gtk_box_pack_start( GTK_BOX( vbox ), button, FALSE, FALSE, 0 );
    gtk_widget_show_all( window );
  
    gtk_main();

    return FALSE;
}

可前進后退的提示窗口

04_notify_window.c

#include <gtk/gtk.h>

// XPM格式圖像數據
static char * book_open_xml[] = {
	"16 16 4 1",
	" c None s None",
	". c black",
	"X c #808080",
	"o c white",
	" ",
	" .. ",
	" .Xo. ... ",
	" .Xoo. ..oo. ",
	" .Xooo.Xooo... ",
	" .Xooo.oooo.X. ",
	" .Xooo.Xooo.X. ",
	" .Xooo.oooo.X. ",
	" .Xooo.Xooo.X. ",
	" .Xooo.oooo.X. ",
	" .Xoo.Xoo..X. ",
	" .Xo.o..ooX. ",
	" .X..XXXXX. ",
	" ..X....... ",
	" .. ",
	" "
};

// 自定義提示
static gchar *info[5] = {
   "此軟件用於測試每日提示功能的實現,如果你發現問題請及時回復。",
   "我們的目的是把GTK+2.0的大多數功能奉獻給每一位自由軟件愛好者和開發者。",
   "每一位Linux的支持者都會讓我們增加一分信心,Linux最終仍是台式計算機操作系統。",
   "計算機軟件技術是一種科學技術,它和人類歷史上其他的科學技術一樣,是允許每一人自由使用的。",
   "當前你測試完此程序后,請設法把它附加到你創作的軟件當中去,這是你成功的第一步。"
};

static GtkWidget *window;			// 主窗口
static GtkWidget *frame;			// 框架
static GtkWidget *pre_button;		// 上一提示按鈕
static GtkWidget *next_button;		// 下一提示按鈕
static GtkWidget *label;			// 提示信息內容標簽
static GtkWidget *title;			// 框架標題

gint current_info = 0;				// 當前提示信息計數

// 創建框架控件標題
GtkWidget* create_title( GtkWidget *data )
{
	GtkWindow *title;
	GtkWindow *hbox;
	GtkWindow *image;
	GtkWindow *label;
	GtkWindow *pixmap;
	GtkWindow *mask;
	GdkWindow *window;

	pixmap = gdk_pixbuf_new_from_xpm_data ( book_open_xml );
	image = gtk_image_new_from_pixbuf( pixmap );
	label = gtk_label_new( "新的標題" );
	hbox = gtk_hbox_new( FALSE, 0 );

	gtk_box_pack_start( GTK_BOX( hbox ), image, FALSE, FALSE, 2 );
	gtk_box_pack_start( GTK_BOX( hbox ), label, FALSE, FALSE, 2 );

	return hbox;
}

GtkWidget* create_button( gchar* stockid, gchar* title )
{
	GtkWidget *button;
	GtkWidget *image;
	GtkWidget *label;
	GtkWidget *hbox;

	image = gtk_image_new_from_stock( stockid, GTK_ICON_SIZE_MENU );
	label = gtk_label_new( title );
	hbox = gtk_hbox_new( FALSE, 0 );
	gtk_box_pack_start( GTK_BOX( hbox ), image, FALSE, FALSE, 3 );
	gtk_box_pack_start( GTK_BOX( hbox ), label, FALSE, FALSE, 3 );
	
	button = gtk_button_new();
	gtk_container_add( GTK_CONTAINER(button), hbox );
	
	return button;
}

// 上一提示
void pre_info( GtkButton *button, gpointer data )
{
	gint i;
	i = current_info - 1;
	if (i == -1 ) return;
	if (i == 0  ) gtk_widget_set_sensitive( pre_button, FALSE );
	current_info = i;
	gtk_widget_set_sensitive( next_button, TRUE );
	gtk_label_set_text( GTK_LABEL( label ), info[current_info] ); 
}

// 下一提示
void next_info( GtkButton *button, gpointer data )
{
	gint i;
	i = current_info + 1;
	if (i == 5 ) return;
	if (i == 4 ) gtk_widget_set_sensitive( next_button, FALSE );
	current_info = i;
	gtk_widget_set_sensitive( pre_button, TRUE );
	gtk_label_set_text( GTK_LABEL( label ), info[current_info] ); 
}

int main( int argc, char* argv[] )
{
	GtkWidget *hbox;
	GtkWidget *vbox;
	GtkWidget *bbox;
	GtkWidget *button;
	GtkWidget *image;
	GtkWidget *title;

	gtk_init( &argc, &argv );
	window = gtk_window_new( GTK_WINDOW_TOPLEVEL );
	g_signal_connect( G_OBJECT( window ), "delete_event", G_CALLBACK( gtk_main_quit ), NULL );

	gtk_window_set_title( GTK_WINDOW( window ), "每日提示" );
	gtk_window_set_position( GTK_WINDOW( window ), GTK_WIN_POS_CENTER );
	gtk_container_set_border_width( GTK_CONTAINER( window ), 10 );
	gtk_widget_realize( window );

	vbox = gtk_vbox_new( FALSE, 0 );
	gtk_container_add( GTK_CONTAINER( window ), vbox );
	
	hbox = gtk_hbox_new( FALSE, 0 );
	gtk_box_pack_start( GTK_BOX( vbox ), hbox, TRUE, TRUE, 5 );
	
	image = gtk_image_new_from_file( "gnome-desktop.png" );
	gtk_box_pack_start( GTK_BOX( hbox ), image, FALSE, FALSE, 5 );
	
	frame = gtk_frame_new( NULL );
	title = create_title( window );
	gtk_frame_set_label_widget( GTK_FRAME( frame ), title );
	gtk_box_pack_start( GTK_BOX( hbox ), frame, TRUE, TRUE, 5 );

	label = gtk_label_new( NULL );
	gtk_label_set_text( GTK_LABEL( label ), info[0] );
	gtk_label_set_line_wrap( GTK_LABEL( label ), TRUE );
	gtk_container_add( GTK_CONTAINER( frame ), label );

	bbox = gtk_hbutton_box_new();
	gtk_button_box_set_layout( GTK_BUTTON_BOX( bbox ), GTK_BUTTONBOX_END );
	gtk_box_pack_start( GTK_BOX( vbox ), bbox, FALSE, FALSE, 5 );

	button = gtk_check_button_new_with_label( "每次啟動時顯示" );
	gtk_box_pack_start( GTK_BOX( bbox ), button, FALSE, FALSE, 5 );

	pre_button = create_button( GTK_STOCK_GO_BACK, "上一提示" );
	gtk_widget_set_sensitive ( pre_button, FALSE );
	g_signal_connect( G_OBJECT( pre_button ), "clicked", G_CALLBACK( pre_info ), NULL );
	gtk_box_pack_start( GTK_BOX( bbox ), pre_button, FALSE, FALSE, 5 );
	
	next_button = create_button( GTK_STOCK_GO_FORWARD, "下一提示" );
	g_signal_connect( G_OBJECT( next_button ), "clicked", G_CALLBACK( next_info ), NULL );
	gtk_box_pack_start( GTK_BOX( bbox ), next_button, FALSE, FALSE, 5 );
	
	button = gtk_button_new_from_stock( GTK_STOCK_OK );
	g_signal_connect( G_OBJECT( button ), "clicked", G_CALLBACK( gtk_main_quit ), NULL );
	gtk_box_pack_start( GTK_BOX( bbox ), button, FALSE, FALSE, 5 );

	gtk_widget_show_all( window );
	gtk_main();

	return FALSE;
}

... 后面有空繼續更新

總結

gtk+ 現有資料已經很少了, 屬於淘汰型技術了, 勿深究.


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM