วันพฤหัสบดีที่ 10 มีนาคม พ.ศ. 2565

Gtk4 ตอนที่ 3 GtkTextView, GtkTextbuffer and GtkScrolledWindow

 ผ่านพื้นฐานทั่วไปมา 2 ตอนแล้ว ตอนที่ 3 นี้จะนำเสนอวิธีการสร้าง GtkTextView เพื่อแสดงข้อความและแก้ไขในข้อความแบบ Multi-line คือ ใส่ข้อความยาวๆ หลายบรรทัดได้

ตัวอย่างโปรแกรม

 1 #include <gtk/gtk.h>
 2 
 3 static void
 4 app_activate (GApplication *app, gpointer user_data) {
 5   GtkWidget *win;
 6   GtkWidget *tv;
 7   GtkTextBuffer *tb;
 8   gchar *text;
 9 
10   text =
11       "Once upon a time, there was an old man who was called Taketori-no-Okina. "
12       "It is a japanese word that means a man whose work is making bamboo baskets.\n"
13       "One day, he went into a mountain and found a shining bamboo. "
14       "\"What a mysterious bamboo it is!,\" he said. "
15       "He cut it, then there was a small cute baby girl in it. "
16       "The girl was shining faintly. "
17       "He thought this baby girl is a gift from Heaven and took her home.\n"
18       "His wife was surprized at his tale. "
19       "They were very happy because they had no children. "
20       ;
21   win = gtk_application_window_new (GTK_APPLICATION (app));
22   gtk_window_set_title (GTK_WINDOW (win), "Taketori");
23   gtk_window_set_default_size (GTK_WINDOW (win), 400, 300);
24 
25   tv = gtk_text_view_new ();
26   tb = gtk_text_view_get_buffer (GTK_TEXT_VIEW (tv));
27   gtk_text_buffer_set_text (tb, text, -1);
28   gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (tv), GTK_WRAP_WORD_CHAR);
29 
30   gtk_window_set_child (GTK_WINDOW (win), tv);
31 
32   gtk_widget_show (win);
33 }
34 
35 int
36 main (int argc, char **argv) {
37   GtkApplication *app;
38   int stat;
39 
40   app = gtk_application_new ("com.github.ToshioCP.tfv1", G_APPLICATION_FLAGS_NONE);
41   g_signal_connect (app, "activate", G_CALLBACK (app_activate), NULL);
42   stat = g_application_run (G_APPLICATION (app), argc, argv);
43   g_object_unref (app);
44   return stat;
45 }


จากตัวอย่างโปรแกรม ดูบรรทัดที่ 25 อินสแตนซ์ GtkTextView ถูกสร้างขึ้นในชื่อ tv ขณะเดียวกัน GtkTextBuffer ก็ถูกสร้างขึ้นพร้อมๆ กันโดยอัตโนมัติ เวลาเราจะใช้งาน buffer ที่สร้างขึ้นก็อ้างอิงผ่าน GtkTextBuffer *tb ที่เราสร้างไว้ตอนต้น ผ่านฟังค์ชันที่เกี่ยวข้อง

โดยหลักการแล้ว GTK มี GtkTextView ไว้เป็น widget สำหรับการแสดงข้อความแบบหลายบรรทัด และใช้ GtkTextBuffer เป็น widget สำหรับแก้ไข แต่ทั้งสองจะเกิดขึ้นพร้อมกันในคราวเดียวกัน หากต้องการกำหนดให้กล่องข้อความนั้นอ่านได้อย่างเดียวให้ใช้กำหนดพร็อพเพอร์ตี้ set_editable ให้เป็น FALSE ดังนี้

  gtk_text_view_set_editable(GTK_TEXT_VIEW(tv), FALSE);

โดยให้กำหนดหลังสุด ให้กำหนดรายละเอียดอื่นๆ ก่อน หรือกำหนดก่อนจะแสดงผล 

สำหรับ GtkTextView นี้จะกำหนดข้อความเป็นแบบ UTF-8 ดังนั้นเราสามารถพิมพ์ภาษาไทยได้ทันที และสามารถกำหนด Tag เช่น ตัวหนา ตัวเอียง ขีดเส้นใต้ ฯลฯ นับว่าสะดวกและยืดหยุ่นแก่การใช้งาน (รายละเอียดลึกๆ จะทำบทความแยกต่างหากจะได้เจาะคุณสมบัติต่างๆ อีกที)

จากนั้นเราก็กำหนด wrap mode คือ การตัดบรรทัดในกล่องข้อความ ในตัวอย่างนี้กำหนดเป็น GTK_WRAP_WORD_CHAR เป็นการตัดคำที่เว้นวรรค 

และบรรทัดที่ 30 เพิ่ม tv เข้าไปเป็น child ของ win และสั่งแสดง win ในบรรทัดต่อมา หลักการคร่าวๆ ก็มีเพียงเท่านี้

หลังจากที่สั่งรันโปรแกรมแล้วจะได้หน้าจอดังนี้



ปัญหาที่พบ คือ เราไม่สามารถควบคุมหน้าต่างได้ ไม่ว่าจะพยายามปรับให้เล็กลง ก็ยังมองไม่เห็นขอบล่างของกล่องข้อความ วิธีการแก้ไขปัญหา ให้เพิ่ม GtkScrolledWindow แทรกระหว่าง GtkApplicationWindow ดังนี้

 1 #include <gtk/gtk.h>
 2 
 3 static void
 4 app_activate (GApplication *app, gpointer user_data) {
 5   GtkWidget *win;
 6   GtkWidget *scr;
 7   GtkWidget *tv;
 8   GtkTextBuffer *tb;
 9   gchar *text;
10 
11   text =
12       "Once upon a time, there was an old man who was called Taketori-no-Okina. "
13       "It is a japanese word that means a man whose work is making bamboo baskets.\n"
14       "One day, he went into a mountain and found a shining bamboo. "
15       "\"What a mysterious bamboo it is!,\" he said. "
16       "He cut it, then there was a small cute baby girl in it. "
17       "The girl was shining faintly. "
18       "He thought this baby girl is a gift from Heaven and took her home.\n"
19       "His wife was surprized at his tale. "
20       "They were very happy because they had no children. "
21       ;
22   win = gtk_application_window_new (GTK_APPLICATION (app));
23   gtk_window_set_title (GTK_WINDOW (win), "Taketori");
24   gtk_window_set_default_size (GTK_WINDOW (win), 400, 300);
25 
26   scr = gtk_scrolled_window_new ();
27   gtk_window_set_child (GTK_WINDOW (win), scr);
28 
29   tv = gtk_text_view_new ();
30   tb = gtk_text_view_get_buffer (GTK_TEXT_VIEW (tv));
31   gtk_text_buffer_set_text (tb, text, -1);
32   gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (tv), GTK_WRAP_WORD_CHAR);
33 
34   gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (scr), tv);
35 
36   gtk_widget_show (win);
37 }
38 
39 int
40 main (int argc, char **argv) {
41   GtkApplication *app;
42   int stat;
43 
44   app = gtk_application_new ("com.github.ToshioCP.tfv2", G_APPLICATION_FLAGS_NONE);
45   g_signal_connect (app, "activate", G_CALLBACK (app_activate), NULL);
46   stat = g_application_run (G_APPLICATION (app), argc, argv);
47   g_object_unref (app);
48   return stat;
49 }



สังเกตจากโค้ดโปรแกรมด้านบน บรรทัดที่เป็นสีแดง คือ บรรทัดที่เพิ่มเข้ามาและแก้ไขให้ใช้ GtkScrolledWindow  เมื่อสั่งรันโปรแกรมแล้วจะได้หน้าจอดังนี้ 

ทั้งหมดนี้ก็เป็นตัวอย่างและหลักการคร่าวๆ ของ GtkTextView, GtkTextBuffer และ GtkScrolledWindow รายละเอียดลึกๆ จะนำมาแยกเขียนอีกทีภายหลัง...


เรียบเรียงจาก
https://github.com/ToshioCP/Gtk4-tutorial/blob/main/gfm/sec5.md

ไม่มีความคิดเห็น:

แสดงความคิดเห็น

Gtk4 ตอนที่ 6 Defining a Child object

Defining a Child object A Very Simple Editor ในบทความที่ผ่านมาเราสร้างโปรแกรมอ่านไฟล์ชนิดข้อความ และในบทความนี้ก็จะมาปรับแต่งโปรแกรมกันสักหน...