15. Gtk Popover Menu
ปัจจุบันเราจะเห็นเมนูในระบบโทรศัพท์หรือแท็ปเล็ตมักจะมีเมนู 3 ขีด แนวขวาง บางทีก็เรียกว่าแฮมเบอร์เกอร์ไลน์ และทั่วไปเราก็รู้จักเมนูแบบ Popup และ Drop down เมนูมาบ้างแล้ว แต่สำหรับ Popover ก็คล้ายๆ เมนูทั้งสองแบบ เพียงแต่จะมีรูปแบบเป็น buble context เหมือนมีมีกรอบคำพูดขึ้นมานั่นแหละ
ก่อนที่จะทำให้เป็นเมนูนั้นจะเริ่มจากวิธีการง่ายๆ ก่อน คือ สร้างปุ่มแฮมเบอร์เกอร์ไลน์ ให้คลิกเรียก Popover ก่อน
เริ่มจากสร้าง Window สำหรับรองรับตามรูปแบบของ Gtk+ โดยเริ่มโครงร่างของโปรแกรม Gtk+ ของภาษา C ดังนี้
/*
* Build:
* gcc $(pkg-config --cflags gtk+-3.0) popover_sample.c -o popover_sample $(pkg-config --libs gtk+-3.0)
*/
#include <gtk/gtk.h>
int main (int argc, char *argv[]){ GtkWidget *window;
GtkWidget *button, *popover, *vbox;
gtk_init (&argc, &argv); // เขียนโค้ดเพิ่มตรงนี้ gtk_main ();
return 0;
}
จากนั้นแทรกโค้ดเข้าไปใต้คอมเม้นท์ //เขียนโค้ดเพิ่มตรงนี้ ตามนี้
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_widget_realize (window);
gtk_window_set_position (GTK_WINDOW (window), GTK_WIN_POS_CENTER);
gtk_container_set_border_width (GTK_CONTAINER (window), 5);
gtk_window_set_default_size (GTK_WINDOW (window), 640, 480);
คำสั่งที่สร้างเพิ่มจะสร้าง GtkWidget ชื่อ window ขึ้นมาเพื่อใช้อ้างอิงถึงหน้าจอที่เราต้องการใช้งาน โดยกำหนดให้เป็น GTK_WINDOW_TOPLEVEL เพื่อให้หน้าต่างนี้อยู่บนสุดเมื่อสั่งรันโปรแกรม
กรณีที่เรียกใช้ gtk_popover จะมีการวาดกราฟฟิกโดยเรียกฟังค์ชัน gdk อีกที ทำให้บางครั้งเกิดข้อความเตือนว่า
gdk_window_get_window_type: assertion ‘GDK_IS_WINDOW (window)’ failed
ให้เพิ่ม gtk_widget_realize(window) ไว้ใต้การสร้าง window ก่อน หรือจะเอาไว้ก่อนฟังค์ชัน gtk_widget_show_all (popover); ก็ได้
หลังจากนั้นก็กำหนดรูปแบบของหน้าต่างที่จะแสดงผล
ต่อมาเราจะสร้างปุ่ม 3 ขีดเพื่อรองรับเมนูแบบ Popover ดังนี้
button = gtk_menu_button_new ();
gtk_button_set_image (GTK_BUTTON (button),
gtk_image_new_from_icon_name ("open-menu-symbolic",
GTK_ICON_SIZE_BUTTON));
gtk_widget_set_valign (button, GTK_ALIGN_START);
gtk_widget_set_halign (button, GTK_ALIGN_START);
gtk_container_add (GTK_CONTAINER (window), button);
บรรทัดแรกสร้างปุ่มขึ้นมา 1 ปุ่มให้ชื่ออ้างอิงว่า button ถัดมากำหนดรูปใส่ในปุ่มโดยใช้ open-menu-symbolic เป็นการกำหนดรูป 3 ขีดให้กับปุ่มและกำหนดขนาดของรูปให้เท่ากับขนาดของปุ่ม
ถัดมาสองบรรทัดกำหนดให้ปุ่มแสดงบนสุด (valign = GTK_ALIGN_START) และกำหนดให้แสดงชิดซ้าย (halign = GTK_ALIGN_START)
สุดท้ายบรรจุปุ่มที่สร้างเข้าไปกับ window
ต่อไปก็จะสร้าง vbox เพื่อบรรจุข้อความสำหรับทำ popover menu ดังนี้
vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
gtk_box_pack_start (GTK_BOX (vbox),
gtk_label_new ("แฟ้มข้อมูลหลัก"), FALSE, FALSE, 0);
gtk_box_pack_start (GTK_BOX (vbox),
gtk_label_new ("ทำรายการ"), FALSE, FALSE, 0); gtk_box_pack_start (GTK_BOX (vbox),
gtk_label_new ("รายงาน"), FALSE, FALSE, 0); gtk_box_pack_start (GTK_BOX (vbox),
gtk_label_new ("จัดการระบบ"), FALSE, FALSE, 0);
บรรทัดแรกสร้าง vbox กำหนดให้เรียงวัตถุภายในเป็นแบบ Vertical หรือแบบบนลงล่าง บรรทัดต่อมาสร้างข้อความผ่านฟังค์ชัน gtk_label_new แล้วเอาไปบรรจุเข้ากับ vbox ทั้ง 4 รายการ
popover = gtk_popover_new (button);
gtk_container_add (GTK_CONTAINER (popover), vbox);
gtk_menu_button_set_popover (GTK_MENU_BUTTON (button), popover);
gtk_widget_show_all (popover);
ต่อมาลำดับสำคัญ คือ การสร้าง popover ผ่านฟังค์ชัน gtk_popover_new() แล้วเอาข้อความที่อยู่ใน vbox ที่ได้จากข้างบนไปเก็บไว้ใน popover ที่สร้างขึ้น
และถัดมาก็นำเอา popover ที่มีข้อความใน vbox ไปบรรจุไว้ใน button อีกที โดยกำหนดผ่าน gtk_menu_button_set_popover และสั่งแสดง popover อีกที
g_signal_connect (G_OBJECT (window), "destroy",
G_CALLBACK (gtk_main_quit), NULL);
gtk_widget_show_all (window);
สุดท้ายก็กำหนดการเชื่อมต่อ signal ไปยัง window โดยกำหนดให้เรียกฟังค์ชัน gtk_main_quit เมื่อคลิกปุ่มปิดหน้าจอ
บรรทัดต่อมาก็สั่งแสดง widget ทั้งหมดที่มีในหน้าจอ แล้วไปรอวนลูปใน gtk_main() เป็นลำดับสุดท้าย จนกว่าเราจะปิดหน้าจอ ถึงจะ return 0 กลับไปยังระบบเป็นอันเสร็จสิ้นกระบวนการ
โปรแกรมนี้เมื่อคอมไพล์และสร้างโปรแกรมแล้ว สั่งรันจะได้หน้าจอเหมือนรูปข้างบนสุด ซึ่งจะแสดงข้อความในกรอบ เมื่อคลิกปุ่ม 3 ขีด หรือปุ่มแฮมเบอร์เกอร์ไลน์
สรุปรูปแบบ
button_set_popover <- popover <- contained vbox <- contained label
ตัวอย่างโปรแกรมต้นฉบับ