Gtk+/GNOMEに関するいろいろ。
gtk+クラス図 (gtk 1.2 to gtk3) gtk+ 1.2 のクラスが残っているかどうか.
1999.07.26 epingle
1999.02.14 gtk+のC++ラッパー
gtk-list MLにおける私の発言から。
A: GtkButtonはGtkBinのサブクラスなので,GTK_BIN(button)->child
(1999.08.24)
A: "focus_in_event"シグナルをafterで接続して,ハンドラでgdk_im_end()すればよい。
gint on_focus_in_event(GtkWidget*widget, GdkEventFocus* event, void* ) { gdk_im_end(); return FALSE; } gtk_signal_connect_after(GTK_OBJECT(entry), "focus_in_event", GTK_SIGNAL_FUNC(on_focus_in_event), NULL);
日本語テキストが貼り付けられる場合があるので,エントリに日本語が入らないようにする場合は,さらに工夫が必要。
(1999.08.20)
A: 次のようにして求める。
int getSelectedIndex(GtkOptionMenu* option_menu) { GtkWidget* menu = gtk_option_menu_get_menu(option_menu); return g_list_index(GTK_MENU_SHELL(menu)->children, option_menu->menu_item); }(1999.07.26)
A: 次のようにする。GtkOptionMenuではなく,構成しているメニューの方に接続するのがミソ。
void on_selection_done(GtkMenuShell* menu_shell, void* ) { ... } GtkWidget* menu = gtk_option_menu_get_menu( GTK_OPTION_MENU(option_menu)); gtk_signal_connect(GTK_OBJECT(menu), "selection-done", GTK_SIGNAL_FUNC(on_selection_done), NULL);(1999.07.26)
A: "expose_event"のハンドラで描画するのが基本。再描画の必要が生じた場合も直接このハンドラを呼ぶのではなく,gtk_widget_queue_draw_area()で領域が無効になったことを示し,gtk+にコールバックさせる。
(1999.07.07)
A: gladeがお勧め。
(1999.06.26)
A: gdkx.hを参照してください。gtk+がクロスプラットフォームを志向しているといっても,全く不完全なので,無理にXの機能を避けるより,積極的に使って問題ない。
#include <gdk/gdkx.h>(1999.04.27)
A: シグナルのハンドラでTRUEを返しても標準の動作が行われる場合や,戻り値がない場合は,gtk_signal_emit_stop_by_name()関数を使います。
void onDaySelected(GtkCalendar* calen, void* data) // GtkCalendar::day_selected { if (mouse_button == MENU_BUTTON) { gtk_signal_emit_stop_by_name(GTK_OBJECT(calen), "day_selected"); return; } ... }(1999.03.21)
A: "map"シグナルを調べてみましょう。
GtkWidget* menu = gtk_item_factory_get_widget( frame->menuFactory, "/ウィンドウ(W)"); gtk_signal_connect(GTK_OBJECT(menu), "map", GTK_SIGNAL_FUNC(onMap), 2);GtkItemFactoryを使わない場合は,GtkMenu派生オブジェクトに"map"シグナルを接続します。次の場合だと,o1ではなく,o2の方です。
gtk_menu_item_set_submenu(GTK_MENU_ITEM(o1), o2);(1999.02.08)
A: ウィンドウ・マネージャがWindowMakerなら,~/GNUstep/Defaults/WMWindowAttributesファイルに次の内容を加える。twmなら回避できない。
IMサーバーにQ's Nicolatterを使う,という選択でも良い。
Kinput2 = { Unfocusable = Yes; };(1999.01.09)
A: "delete_event"イベント。このハンドラでFALSEを返すと標準の動作となり,ウィンドウが"destroy"される。
(1999.01.04)
#include <gtk/gtk.h> int main(int argc, char* argv[]) { gtk_set_locale(); gtk_init(&argc, &argv); GtkWidget* top = gtk_window_new(GTK_WINDOW_TOPLEVEL); GtkMisc* label = GTK_MISC(gtk_label_new("MMM TEST MMM")); gtk_widget_show(GTK_WIDGET(label)); gtk_container_add(GTK_CONTAINER(top), GTK_WIDGET(label)); gtk_widget_show(top); gtk_main(); return 0; }
これで,ウィンドウ一杯にラベルが表示される(ラベルの大きさにウィンドウが調節される)。ウィンドウの大きさを変えると,ラベルは中央に表示される。
gtk_misc_set_alignment(label, 0.0, 0.5); // 左寄せ
すると,ウィンドウの大きさを変えたときに,左端,上下方向は中央に表示されるようになる。
gtk_misc_set_padding(label, 30, 10);を追加すると,ラベルの外側に詰め物が入る。ただしラベルwidgetの大きさは詰め物を含むから,gtk_widget_set_usize()のときに詰め物の幅を考慮する必要がある。この例ではウィンドウを広げるとラベルは左寄りになる。詰め物の幅は親widgetの大きさに左右されず,詰め物とラベル文字列の間の領域が変化する。
GtkItemFactory ---> GtkMenu ^gtk_item_factory_get_widget()
ブランチを利用不可にしたいときは, gtk_item_factory_get_widget() + gtk_menu_get_attach_widget() でMenuItemを取得して,それを操作。
GtkMenuにGtkMenuItemを
GtkContainer::remove()ってpure virtualになってる。
┌────────────┐ │GtkContainer {abstract} │ └────────────┘ △ │ ┌─────┴──────┐ children *┌───┐ │GtkMenuShell {abstract} │◆───────┤void* │MenuItemが入っている └────────────┘ └───┘ △ ├────┐ ┌──┴──┐┌┴───┐ │GtkMenuBar││GtkMenu │GtkMenuはポップアップして,ウィンドウになれる。 └─────┘└────┘
GtkMenuItemはGtkBinから派生していて,ラベルはGtkBin::childに入っている。GtkLabelにキャストして,ラベル文字列を変更すればよい。
┌─────────┐ child ┌─────┐ │GtkBin {abstract} │◆────┤GtkWidget │MenuItemのときラベルが入ってる └─────────┘ └─────┘ △ │ ┌────┴────┐ │GtkItem {abstract}│ └─────────┘ △ │ ┌──┴───┐ │GtkMenuItem │ └──────┘
┌────────────┐ │GtkContainer {abstract} │ └────────────┘ △ ├──────────┐ ┌────┴────┐┌────┴─────┐ child1 ┌─────┐ │GtkBox {abstract} ││GtkPaned {abstract} │◆────┤GtkWidget │ └─────────┘└──────────┘ └─────┘ ◆ ◆ child2 ┌─────┐ │* children └────┤GtkWidget │ ┌─┴─┐ └─────┘ │void* │GtkBoxChild └───┘
gtk_container_border_width(aContainer, ...);は,親widgetとaContainerとの間に空白を作る。aContainerの内側に空白を作るときは,
GtkWidget* textBox = gtk_hbox_new(FALSE, 0); gtk_widget_show(textBox); gtk_container_add(aContainer, textBox); gtk_container_set_border_width(GTK_CONTAINER(textBox), 5);みたいに,単に空白のためだけのboxを用意してやる必要がある。(中身がコンテナの時は,そのコンテナのgtk_container_border_width()でよい。)
gtk_container_set_border_width()はコンテナwidgetの外側に詰め物を入れるが,widgetの大きさには詰め物が含まれる。この辺はgtk_misc_set_padding()でも同様。
gtk_box_pack_start()の場合は,box widgetの内側,子widgetの外側に詰め物を入れる。この場合は,詰め物が子widgetの大きさに含まれない点でgtk_misc_set_padding()等と異なる。ただ,外側といっても囲むわけではなく,また,一つ一つの子widgetの外側に詰め物を入ていくと,(指定する幅が同じなら)widgetが並ぶところの詰め物の幅は,一番外側の幅の2倍になる。
GtkBoxで子widget間の詰め物と外側の詰め物の幅を同じにしようと思うと,gtk_container_set_border_width()とgtk_hbox_new() / gtk_vbox_new()を組み合わせるのがよい。
GtkWidget* box = gtk_hbox_new(FALSE, 20); // (2) 子widget間の詰め物 gtk_container_set_border_width(GTK_CONTAINER(box), 20); // (1) 外側の詰め物gtk_box_pack_start()では詰め物に'0'を指定することに注意しよう。