15. Gtk Popover Menu

Yothin Inbanleng
2 min readMay 26, 2021

--

ปัจจุบันเราจะเห็นเมนูในระบบโทรศัพท์หรือแท็ปเล็ตมักจะมีเมนู 3 ขีด แนวขวาง บางทีก็เรียกว่าแฮมเบอร์เกอร์ไลน์ และทั่วไปเราก็รู้จักเมนูแบบ Popup และ Drop down เมนูมาบ้างแล้ว แต่สำหรับ Popover ก็คล้ายๆ เมนูทั้งสองแบบ เพียงแต่จะมีรูปแบบเป็น buble context เหมือนมีมีกรอบคำพูดขึ้นมานั่นแหละ

ตัวอย่างเมนูแบบ Popover ของ Gtk+

ก่อนที่จะทำให้เป็นเมนูนั้นจะเริ่มจากวิธีการง่ายๆ ก่อน คือ สร้างปุ่มแฮมเบอร์เกอร์ไลน์ ให้คลิกเรียก 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

ตัวอย่างโปรแกรมต้นฉบับ

--

--

Yothin Inbanleng
Yothin Inbanleng

Written by Yothin Inbanleng

สนใจเรียนรู้โดยเฉพาะการเขียนโปรแกรมด้านฐานข้อมูล ไมโครคอนโทรเลอร์ และงานอิเลกโทรนิคส์ ส่วนด้านอื่นๆ ชอบศึกษาประวัติศาสตร์, ถ่ายรูป,ᨲᩫ᩠ᩅᨾᩮᩥ᩠ᨦ, ธรรมะและการบริหาร

No responses yet