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

八、ui窗体创建要点

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

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

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

    window = g_object_new (TEST_TYPE_WINDOW,
                           "default-height", 550, "default-width", 800,
                           "title", "Nice window!",
                           NULL);

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

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

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

struct _TestWindow
{
  GtkWindow  parent_instance;

  /* Template widgets */
  GtkHeaderBar        *header_bar;
  GtkLabel            *label1;
  GtkButton           *button1;
  GtkButton           *button2;
  GtkGrid             *grid1;
};

G_DEFINE_TYPE (TestWindow, test_window, GTK_TYPE_WINDOW)

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

static void
test_window_class_init (TestWindowClass *klass)
{
  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);

  gtk_widget_class_set_template_from_resource (widget_class, "/org/mongnewer/test/popwindowf.ui");
  gtk_widget_class_bind_template_child (widget_class, TestWindow, header_bar);
  gtk_widget_class_bind_template_child (widget_class, TestWindow, label1);
  gtk_widget_class_bind_template_child (widget_class, TestWindow, button1);
  gtk_widget_class_bind_template_child (widget_class, TestWindow, button2);
  gtk_widget_class_bind_template_child (widget_class, TestWindow, grid1);
static void
test_window_init (TestWindow *self)
{
  gtk_widget_init_template (GTK_WIDGET (self));
  g_signal_connect(GTK_WINDOW(self), "destroy", G_CALLBACK(closewindow), self);
}

如果要创建一个叫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`,显示窗体。

下面是编写的代码

#include <gtk/gtk.h>

void
closewindow(GtkWidget *window, gpointer user_data);

void
newwindow(GtkWindow *window, gpointer user_data)
{
	GtkWindow *windownew = GTK_WINDOW(gtk_window_new());
	gtk_window_set_default_size(GTK_WINDOW(windownew), 400, 300);
	gtk_window_set_title(GTK_WINDOW(windownew), "child window");
	GtkWidget *box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 20);
	gtk_box_set_homogeneous(GTK_BOX(box), TRUE);
	GtkWidget *button = gtk_button_new_with_label("new label");
	gtk_button_set_label(GTK_BUTTON(button), "new pushButton");
	g_signal_connect_swapped(GTK_BUTTON(button), "clicked", G_CALLBACK(&closewindow), windownew);
	g_signal_connect_swapped(GTK_WINDOW(windownew), "destroy", G_CALLBACK(&closewindow), windownew);
	
	GtkWidget *spacer1 = gtk_label_new("");
	GtkWidget *spacer2 = gtk_label_new("");
	
	gtk_box_append(GTK_BOX(box), spacer1);
	gtk_box_append(GTK_BOX(box), button);
	gtk_box_append(GTK_BOX(box), spacer2);
	
	gtk_window_set_child(GTK_WINDOW(windownew), box);
	
	gtk_window_set_transient_for(GTK_WINDOW(windownew), window);
	gtk_window_present(GTK_WINDOW(windownew));
}

void
newwindow1(GtkWindow *window_in, gpointer user_data_in)
{
  GtkBuilder *builder = gtk_builder_new();
  gtk_builder_add_from_file (builder, "builder.ui", NULL);

  /* Connect signal handlers to the constructed widgets. */
  GObject *window = gtk_builder_get_object (builder, "window");
  gtk_window_set_default_size(GTK_WINDOW(window), 600, 350);
  
  GObject *button = gtk_builder_get_object (builder, "button1");
  g_signal_connect_swapped (button, "clicked", G_CALLBACK (closewindow), window);

  button = gtk_builder_get_object (builder, "button2");
  g_signal_connect_swapped (button, "clicked", G_CALLBACK (closewindow), window);

  button = gtk_builder_get_object (builder, "quit");
  g_signal_connect_swapped (button, "clicked", G_CALLBACK (closewindow), window);

  gtk_window_set_transient_for(GTK_WINDOW(window), window_in);
  gtk_widget_show (GTK_WIDGET (window));

  /* We do not need the builder any more */
  g_object_unref (builder);
}

void
closewindow(GtkWidget *window, gpointer user_data)
{
	gtk_window_destroy(GTK_WINDOW(window));
}

static void
activate (GtkApplication* app,
          gpointer        user_data)
{
  GtkWidget *window;

  window = gtk_application_window_new (app);
  gtk_window_set_title (GTK_WINDOW (window), "Parent Window");
  gtk_window_set_default_size (GTK_WINDOW (window), 800, 600);
  
  GtkWidget *box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 20);
  gtk_box_set_homogeneous(GTK_BOX(box), TRUE);
  GtkWidget *button = gtk_button_new();
  GtkWidget *button1 = gtk_button_new();
  gtk_button_set_label(GTK_BUTTON(button), "pushButton");
  gtk_button_set_label(GTK_BUTTON(button1), "pushButton1");
  
  g_signal_connect_swapped(GTK_BUTTON(button), "clicked", G_CALLBACK(&newwindow), window);
  g_signal_connect_swapped(GTK_BUTTON(button1), "clicked", G_CALLBACK(&newwindow1), window);
  g_signal_connect_swapped(GTK_WINDOW(window), "destroy", G_CALLBACK(&closewindow), window);
  
  GtkWidget *spacer1 = gtk_label_new("");
  GtkWidget *spacer2 = gtk_label_new("");
  gtk_box_append(GTK_BOX(box), spacer1);
  gtk_box_append(GTK_BOX(box), button);
  gtk_box_append(GTK_BOX(box), button1);
  gtk_box_append(GTK_BOX(box), spacer2);
  
  gtk_window_set_child(GTK_WINDOW(window), box);
    
  gtk_widget_show (window);
}

int
main (int    argc,
      char **argv)
{
  GtkApplication *app;
  int status;

  app = gtk_application_new ("org.gtk.example", G_APPLICATION_FLAGS_NONE);
  g_signal_connect (app, "activate", G_CALLBACK (activate), NULL);
  status = g_application_run (G_APPLICATION (app), argc, argv);
  g_object_unref (app);

  return status;
}

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

<?xml version="1.0" encoding="UTF-8"?>
<interface>
  <object id="window" class="GtkWindow">
    <property name="title">Grid</property>
    <child>
      <object id="grid" class="GtkGrid">
        <property name="column-homogeneous">True</property>
        <property name="column-spacing">10</property>
        <property name="hexpand">True</property>
        <property name="hexpand-set">True</property>
        <property name="row-homogeneous">True</property>
        <property name="row-spacing">10</property>
        <property name="vexpand">True</property>
        <property name="vexpand-set">True</property>
        <child>
          <object id="spacer1" class="GtkLabel">
            <property name="label"></property>
            <layout>
              <property name="column">0</property>
              <property name="column-span">4</property>
              <property name="row">0</property>
            </layout>
          </object>
        </child>
        <child>
          <object id="button1" class="GtkButton">
            <property name="label">Button 1</property>
            <layout>
              <property name="column">1</property>
              <property name="row">1</property>
            </layout>
          </object>
        </child>
        <child>
          <object id="button2" class="GtkButton">
            <property name="label">Button 2</property>
            <layout>
              <property name="column">2</property>
              <property name="row">1</property>
            </layout>
          </object>
        </child>
        <child>
          <object id="quit" class="GtkButton">
            <property name="label">Quit</property>
            <layout>
              <property name="column">1</property>
              <property name="row">2</property>
              <property name="column-span">2</property>
            </layout>
          </object>
        </child>
        <child>
          <object id="spacer2" class="GtkLabel">
            <property name="label"></property>
            <layout>
              <property name="column">0</property>
              <property name="column-span">4</property>
              <property name="row">3</property>
            </layout>
          </object>
        </child>
      </object>
    </child>
  </object>
</interface>

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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/381065.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

java缓冲流

缓冲流相比较基本流效率更高&#xff0c;因为自带长度的8192缓冲区 缓冲流在io体系中的的位置&#xff1a; 字节缓冲流&#xff1a; 缓冲流的构造方法&#xff1a;输入、输出 **先通过一个练习了解字节缓冲流两个写法&#xff1a; //创建缓冲流对象 BufferedInputStream bis…

零基础学编程怎么入手,中文编程工具构件箱之渐变背景构件用法教程,系统化的编程视频教程上线

零基础学编程怎么入手&#xff0c;中文编程工具构件箱之渐变背景构件用法教程&#xff0c;系统化的编程视频教程上线 一、前言 今天给大家分享的中文编程开发语言工具资料如下&#xff1a; 编程入门视频教程链接 https://edu.csdn.net/course/detail/39036 编程工具及实例…

跟着cherno手搓游戏引擎【22】CameraController、Resize

前置&#xff1a; YOTO.h: #pragma once//用于YOTO APP#include "YOTO/Application.h" #include"YOTO/Layer.h" #include "YOTO/Log.h"#include"YOTO/Core/Timestep.h"#include"YOTO/Input.h" #include"YOTO/KeyCod…

070:vue+cesium: 利用canvas设置线性渐变色材质

第070个 点击查看专栏目录 本示例的目的是介绍如何在vue+cesium中设置线性渐变色的材质,这里使用canvas的辅助方法。 直接复制下面的 vue+cesium源代码,操作2分钟即可运行实现效果. 文章目录 示例效果配置方式示例源代码(共104行)专栏目标示例效果 配置方式 1)查看基础…

每日五道java面试题之java基础篇(三)

第一题. switch 是否能作⽤在 byte/long/String 上&#xff1f; Java5 以前 switch(expr)中&#xff0c;expr 只能是 byte、short、char、int。从 Java 5 开始&#xff0c;Java 中引⼊了枚举类型&#xff0c; expr 也可以是 enum 类型。从 Java 7 开始&#xff0c;expr 还可以…

504. Base 7(七进制数)

题目描述 给定一个整数 num&#xff0c;将其转化为 7 进制&#xff0c;并以字符串形式输出。 问题分析 按照二进制转换的方式进行转换即可 代码 char* convertToBase7(int num) {int count 0;char *x (char *)malloc(sizeof(char)*32);char *y (char *)malloc(sizeof(c…

HCIA--NAT实验

1. 划分网段&#xff0c;配置接口IP地址&#xff0c;内网启用OSPF协议&#xff0c;并配置一对一的NAT&#xff1a; AR1配置&#xff1a; [Huawei]int g0/0/0 [Huawei-GigabitEthernet0/0/0]ip add 10.1.1.1 24 [Huawei-GigabitEthernet0/0/0]int g0/0/1 [Huawei-GigabitEther…

Kafka 入门介绍

目录 一. 前言 二. 使用场景 三. 分布式的流平台 四. Kafka 的基本术语 4.1. 主题和日志 &#xff08;Topic 和 Log&#xff09; 4.2. 分布式&#xff08;Distribution&#xff09; 4.3. 异地数据同步技术&#xff08;Geo-Replication&#xff09; 4.4. 生产者&#xf…

svg 进阶

svg 进阶 svg 应用场景 绘制 icon绘制动画 svg viewport 和 viewBox viewport 是 svg 图像的可见区域 viewBox 是用于在画布上绘制 svg 图形的坐标系统 在一下案例中 svg中 width“500” height“200” 就是可视区域 比如你的svg是100X100但是你的可视区域只有20X20 那么他…

python-游戏篇-初级-超级画板

文章目录 开发环境要求运行方法PyCharmVScode 代码main.pytools.py 效果 开发环境要求 本系统的软件开发及运行环境具体如下。 操作系统&#xff1a;Windows 7、Windows 10。Python版本&#xff1a;Python 3.7.1。开发工具&#xff1a;PyCharm 2018。Python内置模块&#xff…

redis-sentinel(哨兵模式)

目录 1、哨兵简介:Redis Sentinel 2、作用 3、工作模式 4、主观下线和客观下线 5、配置哨兵模式 希望能够帮助到大家&#xff01;&#xff01;&#xff01; 1、哨兵简介:Redis Sentinel Sentinel(哨兵)是用于监控redis集群中Master状态的工具&#xff0c;其已经被集成在re…

【Maven】依赖、构建管理 继承与聚合 快速学习(3.6.3 )

文章目录 Maven是什么&#xff1f;一、Maven安装和配置本地配置文件设置idea配置本地maven 二、基于IDEA的Maven工程创建2.1 Maven工程GAVP属性2.2 Idea构建Maven JavaEE工程 三、Maven工程项目结构说明四、Maven核心功能依赖和构建管理4.1 依赖管理和配置4.2 依赖传递和冲突4.…

Python环境下基于最大离散重叠小波变换和支持向量回归的金融时间序列预测

金融时间序列具有非线性、高频性、随机性等特点&#xff0c;其波动情况不仅与当前股票市场、房地产市场、贸易市场等有强联动性&#xff0c;而且大幅度起伏对于其他市场有较大的影响和冲击。由于金融市场受多种因素影响且各影响因素间也存在一定复杂动态交互关系&#xff0c;导…

css的布局(BFC)

一、css中常规的定位方案 1、普通流 元素按照其在HTML中的先后位置自上而下布局。 行内元素水平排列&#xff0c;当行被占满后换行&#xff1b;块级元素则会被渲染为完整的一行。 所有元素默认都是普通流定位。 2、浮动 元素首先按照普通流的位置出现&#xff0c; 然后根据浮动…

Eclipse安装配置、卸载教程(Windows版)

Eclipse是一个开放源代码的集成开发环境&#xff08;IDE&#xff09;&#xff0c;最初由IBM公司开发&#xff0c;现在由Eclipse基金会负责维护。它是一个跨平台的工具&#xff0c;可以用于开发多种编程语言&#xff0c;如Java、C/C、Python、PHP、Rust等。 Eclipse提供了一个可…

传输频宽是啥?对网速影响有多大?

频宽&#xff0c;即WIFI频道宽度&#xff0c;又称为WIFI信道宽度&#xff0c;是WiFi Channel width的缩写。从科学的定义来说&#xff0c;Wi-Fi频道宽度&#xff0c;是指Wi-Fi无线信号在频谱上所占用的带宽大小。它决定了Wi-Fi网络的数据传输速率和稳定性&#xff0c;一般有20M…

C++ 哈希表(unordered_map与unordered_set)

文章目录 unordered_map 与 unordered_set哈希表 (Hash Table)哈希函数哈希冲突模拟实现封装 补充&#xff1a;unordered_map 与 unordered_set 的使用 unordered_map 与 unordered_set 就和名字一样&#xff0c;这是 map、set 的无序版本&#xff08;数据遍历出来是无序的&am…

STM32标准库移植FreeRTOS并测试

STM32标准库移植FreeRTOS并测试 最终现象一、移植①下载FreeRTOS源码②移植步骤 二、测试三、工程项目 最终现象 主函数中创建三个任务&#xff0c;优先级都相同&#xff0c;意味着每个任务执行固定事件之后就会轮到下一个任务运行&#xff0c;由于这个时间是很短的&#xff0…

免费文字转语音工具,一款优秀且永久免费的文字转语音工具,同时拥有多种类型男声女声,支持多国语言转换,支持语速调节和下载!

一、软件简介 该工具只有一个功能&#xff0c;就是将输入框内的纯文本内容转换为指定语言的音频&#xff0c;并且可以自由调节语速及音色&#xff08;男声/女声&#xff09;&#xff0c;其内置了多种语音包&#xff0c;包含男声、女声、普通话、粤语以及方言&#xff0c;并且支…

Sodinokibi(REvil)勒索病毒最新变种,攻击Linux平台

前言 国外安全研究人员爆光了一个Linux平台上疑似Sodinokibi勒索病毒家族最新样本&#xff0c;如下所示&#xff1a; Sodinokibi(REvil)勒索病毒的详细分析以及资料可以参考笔者之前的一些文章&#xff0c;这款勒索病毒黑客组织此前一直以Windows平台为主要的攻击目标&#xf…
最新文章