当前位置:   article > 正文

Ubuntu22.04 gnome-builder gnome C 应用程序习练笔记(三)

Ubuntu22.04 gnome-builder gnome C 应用程序习练笔记(三)

八、ui窗体创建要点

.h文件定义(popwindowf.h), TEST_TYPE_WINDOW宏是要创建的窗口样式。

  1. #pragma once
  2. #include <gtk/gtk.h>
  3. G_BEGIN_DECLS
  4. #define TEST_TYPE_WINDOW (test_window_get_type())
  5. G_DECLARE_FINAL_TYPE (TestWindow, test_window, TEST, WINDOW, GtkWindow)
  6. G_END_DECLS

g_object_new时生产TEST_TYPE_WINDOW,后面的参数是窗口的属性。

  1. window = g_object_new (TEST_TYPE_WINDOW,
  2. "default-height", 550, "default-width", 800,
  3. "title", "Nice window!",
  4. NULL);

在ui文件里的名字叫  TestWindow ,如果是主窗体,则是项目的  工程名+Window ,如 WithcamblaWindow。 ui文件里的template class名字,要和.h文件中的名字一致。

  1. <template class="TestWindow" parent="GtkWindow">
  2. <property name="default-height">800</property>
  3. <property name="default-width">1200</property>

.c文件中的名字也是一致的, TestWindow是产生的新窗体的 handle

  1. struct _TestWindow
  2. {
  3. GtkWindow parent_instance;
  4. /* Template widgets */
  5. GtkHeaderBar *header_bar;
  6. GtkLabel *label1;
  7. GtkButton *button1;
  8. GtkButton *button2;
  9. GtkGrid *grid1;
  10. };
  11. G_DEFINE_TYPE (TestWindow, test_window, GTK_TYPE_WINDOW)

创建窗体时有两个接口,一是窗口作为一个class的初始化init,另一个是窗体本身的初始化init

  1. static void
  2. test_window_class_init (TestWindowClass *klass)
  3. {
  4. GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
  5. gtk_widget_class_set_template_from_resource (widget_class, "/org/mongnewer/test/popwindowf.ui");
  6. gtk_widget_class_bind_template_child (widget_class, TestWindow, header_bar);
  7. gtk_widget_class_bind_template_child (widget_class, TestWindow, label1);
  8. gtk_widget_class_bind_template_child (widget_class, TestWindow, button1);
  9. gtk_widget_class_bind_template_child (widget_class, TestWindow, button2);
  10. gtk_widget_class_bind_template_child (widget_class, TestWindow, grid1);
  1. static void
  2. test_window_init (TestWindow *self)
  3. {
  4. gtk_widget_init_template (GTK_WIDGET (self));
  5. g_signal_connect(GTK_WINDOW(self), "destroy", G_CALLBACK(closewindow), self);
  6. }

如果要创建一个叫Passwd窗体,则是PASSWD_TYPE_WINDOW(passwd_window_get_type()),

G_DECLARE_FINAL_TYPE (PasswdWindow, passwd_window, PASSWD, WINDOW, GtkWindow),ui文件中template class = PasswdWindow,如此,可以考贝已有的.h和.c,然后改动一个名称,注意保持.h .c ui间的名称一致。创建窗体时,用GtkWindow,或GtkApplicationWindow, 也是注意保持.h .c ui间窗体样式的一致性。

九、工程添加.c和ui文件

meson和make一样,在meson.build中要加入窗体的 .c, make时就一同make了

新窗体的ui文件要写到resource xml 配置中

写起来挺啰嗦,实现起来只是考贝、修改,名称不一致编译时也会有警告提示的。

十、其它注意事项

如果cambalache不能显示图形,关闭cambalache软件使用硬件加速功能,尤其是在虚拟中运行cambalache,因为没有加速的硬件,所以要关闭它,否则不能显示图形。cambalache是flatpak包,需要安装flatseal包,用flatseal关闭cambalache的硬件加速功能。

ubuntu 22.04 mate-desktop 运行gnome-builder遇到闪退问题的话,sudo apt install tasksel, 运行tasksel可选择不同的桌面。

选择gnome桌面可解决问题, 窗口管理器依然选用lightdm,不需要选用 gdm3 管理器。问题遇到了、处理掉,就写在这里吧。

GtkApplication简单化编程

gnome-builder构建器功能多,打包方便,但操作也相对繁琐,网上文档零散、不完整,其实,编程的话可以直接写代码,也可以直接写ui文件(gtk4更适合直接写ui),或是直接用代码创建窗体,这样的话编辑器用简单的geany就可以(可能开始时要辅以gtk4网页帮助),修改界面非常方便。

下面是一个习练的代码程序

geany 代码窗口

在geany下编译 gcc `pkg-config --cflags gtk4` -o "%e" "%f" `pkg-config --libs gtk4`,显示窗体。

下面是编写的代码

  1. #include <gtk/gtk.h>
  2. void
  3. closewindow(GtkWidget *window, gpointer user_data);
  4. void
  5. newwindow(GtkWindow *window, gpointer user_data)
  6. {
  7. GtkWindow *windownew = GTK_WINDOW(gtk_window_new());
  8. gtk_window_set_default_size(GTK_WINDOW(windownew), 400, 300);
  9. gtk_window_set_title(GTK_WINDOW(windownew), "child window");
  10. GtkWidget *box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 20);
  11. gtk_box_set_homogeneous(GTK_BOX(box), TRUE);
  12. GtkWidget *button = gtk_button_new_with_label("new label");
  13. gtk_button_set_label(GTK_BUTTON(button), "new pushButton");
  14. g_signal_connect_swapped(GTK_BUTTON(button), "clicked", G_CALLBACK(&closewindow), windownew);
  15. g_signal_connect_swapped(GTK_WINDOW(windownew), "destroy", G_CALLBACK(&closewindow), windownew);
  16. GtkWidget *spacer1 = gtk_label_new("");
  17. GtkWidget *spacer2 = gtk_label_new("");
  18. gtk_box_append(GTK_BOX(box), spacer1);
  19. gtk_box_append(GTK_BOX(box), button);
  20. gtk_box_append(GTK_BOX(box), spacer2);
  21. gtk_window_set_child(GTK_WINDOW(windownew), box);
  22. gtk_window_set_transient_for(GTK_WINDOW(windownew), window);
  23. gtk_window_present(GTK_WINDOW(windownew));
  24. }
  25. void
  26. newwindow1(GtkWindow *window_in, gpointer user_data_in)
  27. {
  28. GtkBuilder *builder = gtk_builder_new();
  29. gtk_builder_add_from_file (builder, "builder.ui", NULL);
  30. /* Connect signal handlers to the constructed widgets. */
  31. GObject *window = gtk_builder_get_object (builder, "window");
  32. gtk_window_set_default_size(GTK_WINDOW(window), 600, 350);
  33. GObject *button = gtk_builder_get_object (builder, "button1");
  34. g_signal_connect_swapped (button, "clicked", G_CALLBACK (closewindow), window);
  35. button = gtk_builder_get_object (builder, "button2");
  36. g_signal_connect_swapped (button, "clicked", G_CALLBACK (closewindow), window);
  37. button = gtk_builder_get_object (builder, "quit");
  38. g_signal_connect_swapped (button, "clicked", G_CALLBACK (closewindow), window);
  39. gtk_window_set_transient_for(GTK_WINDOW(window), window_in);
  40. gtk_widget_show (GTK_WIDGET (window));
  41. /* We do not need the builder any more */
  42. g_object_unref (builder);
  43. }
  44. void
  45. closewindow(GtkWidget *window, gpointer user_data)
  46. {
  47. gtk_window_destroy(GTK_WINDOW(window));
  48. }
  49. static void
  50. activate (GtkApplication* app,
  51. gpointer user_data)
  52. {
  53. GtkWidget *window;
  54. window = gtk_application_window_new (app);
  55. gtk_window_set_title (GTK_WINDOW (window), "Parent Window");
  56. gtk_window_set_default_size (GTK_WINDOW (window), 800, 600);
  57. GtkWidget *box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 20);
  58. gtk_box_set_homogeneous(GTK_BOX(box), TRUE);
  59. GtkWidget *button = gtk_button_new();
  60. GtkWidget *button1 = gtk_button_new();
  61. gtk_button_set_label(GTK_BUTTON(button), "pushButton");
  62. gtk_button_set_label(GTK_BUTTON(button1), "pushButton1");
  63. g_signal_connect_swapped(GTK_BUTTON(button), "clicked", G_CALLBACK(&newwindow), window);
  64. g_signal_connect_swapped(GTK_BUTTON(button1), "clicked", G_CALLBACK(&newwindow1), window);
  65. g_signal_connect_swapped(GTK_WINDOW(window), "destroy", G_CALLBACK(&closewindow), window);
  66. GtkWidget *spacer1 = gtk_label_new("");
  67. GtkWidget *spacer2 = gtk_label_new("");
  68. gtk_box_append(GTK_BOX(box), spacer1);
  69. gtk_box_append(GTK_BOX(box), button);
  70. gtk_box_append(GTK_BOX(box), button1);
  71. gtk_box_append(GTK_BOX(box), spacer2);
  72. gtk_window_set_child(GTK_WINDOW(window), box);
  73. gtk_widget_show (window);
  74. }
  75. int
  76. main (int argc,
  77. char **argv)
  78. {
  79. GtkApplication *app;
  80. int status;
  81. app = gtk_application_new ("org.gtk.example", G_APPLICATION_FLAGS_NONE);
  82. g_signal_connect (app, "activate", G_CALLBACK (activate), NULL);
  83. status = g_application_run (G_APPLICATION (app), argc, argv);
  84. g_object_unref (app);
  85. return status;
  86. }

下面是简单化的手写ui(复制、粘贴、修改)

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <interface>
  3. <object id="window" class="GtkWindow">
  4. <property name="title">Grid</property>
  5. <child>
  6. <object id="grid" class="GtkGrid">
  7. <property name="column-homogeneous">True</property>
  8. <property name="column-spacing">10</property>
  9. <property name="hexpand">True</property>
  10. <property name="hexpand-set">True</property>
  11. <property name="row-homogeneous">True</property>
  12. <property name="row-spacing">10</property>
  13. <property name="vexpand">True</property>
  14. <property name="vexpand-set">True</property>
  15. <child>
  16. <object id="spacer1" class="GtkLabel">
  17. <property name="label"></property>
  18. <layout>
  19. <property name="column">0</property>
  20. <property name="column-span">4</property>
  21. <property name="row">0</property>
  22. </layout>
  23. </object>
  24. </child>
  25. <child>
  26. <object id="button1" class="GtkButton">
  27. <property name="label">Button 1</property>
  28. <layout>
  29. <property name="column">1</property>
  30. <property name="row">1</property>
  31. </layout>
  32. </object>
  33. </child>
  34. <child>
  35. <object id="button2" class="GtkButton">
  36. <property name="label">Button 2</property>
  37. <layout>
  38. <property name="column">2</property>
  39. <property name="row">1</property>
  40. </layout>
  41. </object>
  42. </child>
  43. <child>
  44. <object id="quit" class="GtkButton">
  45. <property name="label">Quit</property>
  46. <layout>
  47. <property name="column">1</property>
  48. <property name="row">2</property>
  49. <property name="column-span">2</property>
  50. </layout>
  51. </object>
  52. </child>
  53. <child>
  54. <object id="spacer2" class="GtkLabel">
  55. <property name="label"></property>
  56. <layout>
  57. <property name="column">0</property>
  58. <property name="column-span">4</property>
  59. <property name="row">3</property>
  60. </layout>
  61. </object>
  62. </child>
  63. </object>
  64. </child>
  65. </object>
  66. </interface>

ui写着不顺手时装到cambalache里完善一下再export出来接着手改完善,还是比较方便的。

新年到了,祝CSDN朋友们新春快乐、生活轻松幸福!

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/羊村懒王/article/detail/74373
推荐阅读
相关标签
  

闽ICP备14008679号