《GTK+/GNOME程序設計》 筆記(一) GTK+

2016.05.13 筆記

GTK+簡介

GTK 最初爲GIMP(一個圖像處理軟件,類似Photoshop)的工具包
後來GTK重寫爲面向對象的GTK+

GTK+ 並非是用C++寫的,而是用C語言,所謂的面向對象是用C語言模擬的。強大

GTK+ 2.0 新特性:
使用Pango(a theme engine)增強了文本渲染
improved accessibility using the Accessibility Toolkit, transition to Unicode using UTF-8 strings, and a more flexible API.

GTK+ 2.8, GTK+ 2 depends on the Cairo graphics library for rendering vector graphics.

GTK+ 3.0
included revised input device handling, support for themes written with CSS-like syntax, and the ability to receive information about other opened GTK+ applications.

版本的新特性參考 wiki GTK+

編譯

GTK+ 3.0的編譯選項,用法見下文:
pkg-config --cflags gtk+-3.0
pkg-config --libs gtk+-3.0
https://developer.gnome.org/gtk3/stable/gtk-getting-started.html

fedora Linux中安裝gtk+/gnome開發包:
dnf install gnome-devel
dnf install gtk3-devel
dnf install gtk2-devel
dnf install gtk+-devel
dnf install gcc
dnf install gcc-c++

#include <gtk/gtk.h>
void CloseRequest(GtkWidget* theWindow, gpointer data);

gint main(gint argc, gchar* argv[])
{
  GtkWidget* window;

  gtk_init(&argc, &argv);
  window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  gtk_signal_connect(GTK_OBJECT(window), "destroy",
      GTK_SIGNAL_FUNC(CloseRequest), NULL);

  gtk_widget_show(window);
  gtk_main();
  return 0;
}

void CloseRequest(GtkWidget* theWindow, gpointer data)
{
  gtk_main_quit();
}

編譯:
gcc -Wall -o test01 test01.cpp `gtk-config --cflags --libs`

-Wall 輸出所有警告和錯誤

`gtk-config` 飄號中的命令會首先執行,命令執行返回的字符串將替換到該位置,gtk-config將返回編譯選項:所需的頭文件或庫文件等信息。詳情參考Linux命令行中飄號的用法。

GLib

<glib.h>
GLib提供了一些標準的數據類型

gboolean
gpointer
gchar guchar
gint guint gshort
glong gulong
gint8 guint8 gint16
guint16 gint32 guint32
gint64 guint64
gfloat gdouble
gsize
gssize


G_DIR_SEPARATOR 目錄分隔符 單個字符
G_DIR_SEPARATOR_S 0終結的串

G_SEARCHPATH_SEPARATOR PATH 分隔符
G_SEARCHPATH_SEPARATOR_S

MIN(x, y)
MAX(x, y)
ABS() 絕對值
CLAMP(a, x, y)

g_assert()
g_print() 非調試模式可以使用g_set_print_handler()函數忽略
g_assert_not_reached()  用來定義代碼中不應該到達某個點
g_return_if_fail()
g_return_val_if_fail()
g_error() g_set_error_handler()
g_warning() g_set_warning_handler()

glib支持管理有序二叉樹、n叉樹、單向和雙向鏈表的函數
如果glib分配內存的嘗試由於某種原因未成功,則應用程序將終止

g_malloc()
g_free()
g_new(類型, 個數) g_new(char, 50)
g_realloc()
g_memdup() 自動分配一個新內存塊,然後拷貝源塊中的數據到新塊,返回新塊的指針

鏈表

單向鏈表函數名 g_slist開頭
雙向鏈表函數名 g_list 開頭

struct GSList
{
    gpointer data;
    GSList* next;
}

struct GList
{
    gpointer data;
    GList* next;
    GList* prev;
}

建立表是初始化一個表爲NULL

GList* list = NULL;
g_list_free(list)
g_slist_free()

g_list_append()
g_list_prepend()
g_list_insert(list, "data", 1); 索引從0開始,插入的位置
g_list_insert_sorted(list, "data", 比較函數)

創建窗口

X Windows System API

繼承關係

GtkObject
  GtkWidget
    GtkContainer
      GtkBin
        GtkWindow

gtk_window_new()
GTK_WINDOW_TOPLEVEL
GTK_WINDOW_DIALOG
GTK_WINDOW_POPUP

gtk_window開頭 使用GtkWindow
gtk_widget開頭 使用GtkWidget

gtk_main() 啓動GTK+循環

事件和信號

X本身能夠抓住所產生的某些事情,如窗口刪除、點擊按鈕等,這些都爲信號。
GTK+還添加了自己的特定類型,爲事件
在代碼中使用信號和事件沒有區別。

信號連接

gtk_signal_connect(GTK_OBJECT(theWindow), "destroy",
    GTK_SIGNAL_FUNC(StopTheApp), NULL);

GTK_OBJECTtheWindow轉換爲基類對象GtkObject
因爲信號處理程序的聲明不一樣,所以GTK_SIGNAL_FUNC轉換
編寫信號處理程序時,需要查詢信號文檔以便知道處理函數應有的格式。
參考 GTK+/GNOME程序設計附錄A

信號處理程序是事後調用的。這樣,一個窗口取消並且在其取消後調用信號處理程序。

事件是事前產生的。因此,每個窗口有一個稱爲delete_event的事件,該事件在窗口取消前產生。

事件處理程序中:
return TRUE 告訴GTK+我處理了此事件
return FALSE 告訴GTK+我不處理這個事件,你來處理
比如在delete_event處理程序中返回TRUE以禁止GTK+取消窗口
連接事件只需將"destroy"改爲"delete_event"

GdkEvent 參考第三章
GdkEventType

事件類型 “event” 捕獲所有事件

gint gtk_signal_connect()返回處理程序ID

斷開信號處理程序的連接
gtk_signal_disconnect(GTK_OBJECT(myWindow), id);

不使用ID斷開連接:
gtk_signal_disconnect_by_func()

設置窗口標題

gtk_window_set_title(GTK_WINDOW(myWindow), "This is the caption");

gtk_window_set_default_size(GTK_WINDOW(myWindow), 640, 480);

gtk_window_set_position()
GTK_WIN_POS_NONE     GTK+將窗口放在它想放置的位置,默認
GTK_WIN_POS_CENTER   屏幕居中
GTK_WIN_POS_MOUSE    窗口中心和鼠標點相同

gtk_widget_set_uposition()

GTK+的按鈕實際上是一個容器,包含一個文本標籤

將小部件添加到容器的步驟:

  1. 建立需要添加的窗口小部件
  2. 將其添加到容器中
  3. 設置其信號和事件的回調機制
  4. 顯示這個窗口小部件
GtkWidget* AddButton(GtkWidget* theWindow, const gchar* buttonText)
{
    GtkWidget* button;
    button = gtk_button_new_with_label(buttonText);
    gtk_container_add(GTK_CONTAINER(theWindow), button);
    gtk_widget_show(button);
    return button;
}
gtk_signal_connect(GTK_OBJECT(button), "clicked", 
    GTK_SIGNAL_FUNC(ButtonClicked), NULL);

gtk_container_border_width(GTK_CONTAINER(window), 5);

佈局

GtkBox GtkHBox GtkVBox
gtk_hbox_new()
gtk_box_pack_start()
gtk_box_pack_end()

包裝框添加小部件的步驟:

  1. 建立窗口小部件
  2. 將它添加到包裝框中
  3. 顯示它
/* 示例 */
GtkWidget* box;
box = gtk_hbox_new(TRUE, 5); // homogenous 均勻的 第二個參數,小部件間的間距
button = gtk_button_new_with_label(...);
gtk_box_pack_start(GTK_BOX(box), button, 
    FALSE, TRUE, 0);  // expand fill padding
gtk_widget_show(button);
gtk_widget_show(box);

最好建立了窗口的所有內容並準備顯示時再顯示此窗口。否則在速度慢的機器上用戶會看到窗口和用戶界面一點一點建立的過程。

GtkRequisition
  gint16 width
  gint16 height

GtkAllocation
  gint16 x
  gint16 y
  guint16 width
  guint16 height

gtk_widget_show_all() 可以一次顯示所有的窗口小部件

包裝表 GtkTable

gtk_table_new(guint rows, guint columns, gboolean homogenous)

homogenous
TRUE 所有列使用表中最大窗口小部件的寬度,行同理

將窗口小部件添加到表中:
gtk_table_attach_defaults(..., guint left_attach, guint right_attach, ...)

left_attach 0 right_attach 1
表示小部件放在第一列,0 2 表示 橫跨1 2兩列
defaults表示 expand fill padding 爲默認 TRUE TRUE 0
gtk_table_attach()
GtkAttachOptions
GTK_EXPAND GTK_FILL

窗口小部件 GtkLabel

  gtk_label_new(const gchar* str)
  gtk_label_set_text(..., const gchar* str) 空指針表示清除文本
  gtk_label_set_line_wrap() 使文本超過寬度自動換行
  gtk_label_set_justify() 總是垂直居中,無法控制,不能在運行中改變對齊方式,必須在顯示前設置
    GtkJustification
    GTK_JUSTIFY_LEFT GTK_JUSTIFY_FIGHT GTK_JUSTIFY_CENTER GTK_JUSTIFY_FULL

GtkEntry 文本輸入框

  gtk_entry_new(void)
  gtk_entry_new_width_max_length(guint16 max) // 限制字符數
  gtk_entry_set_max_length()
  gtk_entry_get_text()
  gtk_entry_set_text()
  gtk_entry_set_visibility(..., gboolean visible)  // false 用星號顯示,無法定製使用其他符號
  gtk_entry_prepend_text()  // 將文本插入到已有文本前面
  gtk_entry_append_text()

GtkEditable

GtkEditableGtkEntry的基類

  gtk_editable_set_editable()
  gtk_editable_select_region() 高亮選中文本 [start, end)  MAXINT
  剪貼板函數,對選中的文本進行操作
  gtk_editable_cut_clipboard()
  gtk_editable_copy_clipboard()
  gtk_editable_paste_clipboard()

GtkToggleButton

GtkToggleButton 派生於 GtkButton
“toggled” “clicked”

  gtk_toggle_button_new_with_label("Toggle Me")
  gtk_toggle_button_new()
  gtk_toggle_button_get_active()
  gtk_toggle_button_set_active()
  gtk_toggle_button_toggled()

GtkCheckButton

窗口小部件的外觀取決於所使用的窗口管理器,它負責窗口小部件的繪製。

  gtk_check_button_new_with_label()
  gtk_check_button_new()

GtkRadioButton

GtkRadioButton 派生於 GtkCheckButton

步驟:

  1. 建立一個空的GList指針(單向鏈表)
  2. 將列表傳遞給建立單選鈕的函數
  3. 將單選鈕添加到容器中
  4. 顯示單選鈕
  5. 得到從單選鈕中返回的更改過的鏈表
GSList* group = NULL;
GtkWidget* radio;
radio = gtk_radio_button_new_with_label(group, "Some Text");
group = gtk_radio_button_group(radio);

GtkFrame

GtkFrame 一個可視容器,如同窗口一樣只能擁有一個窗口小部件,所以,先將一個Box添加到Frame上

  gtk_frame_set_label_align(..., gfloat xalign, yalign) 0 - 1,標題的顯示位置
  gtk_frame_set_shadow_type()
    GtkShadowType
    GTK_SHADOW
    GTK_SHADOW_IN
    GTK_SHADOW_OUT
    GTK_SHADOW_ETCHED_IN
    GTK_SHADOW_ETCHED_OUT

GtkList 基本的列表框

GtkCList GtkList
GtkList 是一個容器,可將各種窗口小部件添加到此列表中,GtkListItem
GtkListItem也是容器,沒有標籤的可以將任意窗口小部件按鈕或像素映射圖加到其中

  gtk_list_new()
  gtk_list_item_new_with_label()
  gtk_container_add(GTK_CONTAINER(listbox), listitem)
  gtk_widget_show(listitem)
  使用列表
  memeroylist = g_list_append(memorylist, listitem)
  gtk_list_append_items(GTK_LIST(listbox), memorylist)
  gtk_list_set_selection_mode(GTK_LIST(list), GTK_SELECTION_EXTENDED);
連接信號
  gtk_signal_connect(GTK_OBJECT(list), "select_child", ...)
  gtk_signal_connect(GTK_OBJECT(list), "unselect_child", ...)
void ItemPrinter(gpointer data, gpointer userdata)
{
  // data - list item
}
g_list_foreach(list, ItemPrinter, NULL);

GtkCombo

struct GtkCombo
{
  Gtk_HBox hbox;
  GtkWidget* entry;
  GtkWidget* button;
  GtkWidget* popup;
  GtkWidget* popwin;
  GtkWidget* list;
}
gtk_combo_new()
GList* options = NULL;
options = g_list_append(options, "Male");
options = g_list_append(options, "Female");
options = g_list_append(options, "Other");
gtk_combo_set_popdown_strings(GTK_COMBO(mycombo), options);
獲取當前項文本:
gchar* selectedValue;
selectedValue = gtk_enty_get_text(
  GTK_ENTRY(GTK_COMBO(combo)->entry));

GtkCList 多列列表

  gtk_clist_new()
  gtk_clist_new_with_titles()
  gtk_clist_column_titles_show()
  gtk_clist_column_tities_hide()
  gtk_clist_column_title_active()  // 使指定列標題按鈕可點擊
  gtk_clist_column_title_passive()
  gtk_clist_column_titles_active()
  gtk_clist_column_titles_passive()
  gtk_clist_set_column_width()
  gtk_clist_set_row_height()

  gtk_clist_prepend(..., gchar* text[]);
  gtk_clist_append()
  gtk_clist_insert()
  gtk_clist_remove(..., gint row)
  gtk_clist_clear()

  gtk_clist_freeze()  // 更改列表時不刷新,避免閃爍
  gtk_clist_thaw()

  gtk_clist_set_text()
  gtk_clist_get_text()
  gtk_clist_set_pixmap()
  gtk_clist_set_pixtext()

  gtk_clist_select_row()
  gtk_clist_unselect_row()
  gtk_clist_get_selection_info()  // 利用座標所對應的行和列更新row column參數

事件
select_row
unselect_row

對話框

  gtk_window_new(GTK_WINDOW_DIALOG);  // 沒有最大化圖標
  gtk_window_set_modal(..., gboolean modal)  // 模態對話框
  gtk_widget_destroy()  // destroy信號
  gtk_widget_hide()     // hide信號
  gtk_hseparator_new()  // GtkHSeparator 分隔控件

  gtk_main() gtk_main_quit()可以嵌套調用

GtkDialog 內建包裝框

vbox
action_area

GtkFileSelection

文件列表、目錄列表、目錄選擇按鈕、錄入框(顯示文件過濾器和所選文件名)

  gtk_file_selection_new()
  gtk_widget_show()
  gtk_file_selection_set_filename() // 提供缺省文件名

  gtk_file_selection_show_fileop_buttons()
  gtk_file_selection_hide_fileop_buttons()
  gtk_file_selection_complete()   // 希望設置的過濾器的串的指針
  ok_button       成員
  cancel_button   成員
  gtk_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(filedialog)->ok_button), ...)
  gtk_file_selection_get_filename()  // 絕對路徑文件名

GtkColorSelectionDialog

核心小部件 GtkColorSelection
重要成員:
colorsel
ok_button
reset_button
cancel_button
help_button

  gdouble selectedcolor;
  gtk_color_selection_get_color(GTK_COLOR_SELECTION(
      GTK_COLOR_SELECTION_DIALOG(theDialog)->colorsel), & selectedcolor);

待續…

發佈了34 篇原創文章 · 獲贊 21 · 訪問量 14萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章