八、Gtk4-GtkBuilder and UI file

news2024/11/25 16:20:09

1 New, Open and Save button

在上一节中,我们制作了一个非常简单的编辑器。它在程序开始时读取文件,在程序结束时将文件写出来。它可以工作,但不是很好。如果我们有“新建”、“打开”、“保存”和“关闭”按钮就更好了。本节介绍如何在窗口中放置这些按钮。
在这里插入图片描述
上面的截图展示了布局。源代码tfe2.c中的app_open函数如下所示。

 1 static void
 2 app_open (GApplication *app, GFile ** files, gint n_files, gchar *hint) {
 3   GtkWidget *win;
 4   GtkWidget *nb;
 5   GtkWidget *lab;
 6   GtkNotebookPage *nbp;
 7   GtkWidget *scr;
 8   GtkWidget *tv;
 9   GtkTextBuffer *tb;
10   char *contents;
11   gsize length;
12   char *filename;
13   int i;
14 
15   GtkWidget *boxv;
16   GtkWidget *boxh;
17   GtkWidget *dmy1;
18   GtkWidget *dmy2;
19   GtkWidget *dmy3;
20   GtkWidget *btnn; /* button for new */
21   GtkWidget *btno; /* button for open */
22   GtkWidget *btns; /* button for save */
23   GtkWidget *btnc; /* button for close */
24 
25   win = gtk_application_window_new (GTK_APPLICATION (app));
26   gtk_window_set_title (GTK_WINDOW (win), "file editor");
27   gtk_window_set_default_size (GTK_WINDOW (win), 600, 400);
28 
29   boxv = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
30   gtk_window_set_child (GTK_WINDOW (win), boxv);
31 
32   boxh = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
33   gtk_box_append (GTK_BOX (boxv), boxh);
34 
35   dmy1 = gtk_label_new(NULL); /* dummy label for left space */
36   gtk_label_set_width_chars (GTK_LABEL (dmy1), 10);
37   dmy2 = gtk_label_new(NULL); /* dummy label for center space */
38   gtk_widget_set_hexpand (dmy2, TRUE);
39   dmy3 = gtk_label_new(NULL); /* dummy label for right space */
40   gtk_label_set_width_chars (GTK_LABEL (dmy3), 10);
41   btnn = gtk_button_new_with_label ("New");
42   btno = gtk_button_new_with_label ("Open");
43   btns = gtk_button_new_with_label ("Save");
44   btnc = gtk_button_new_with_label ("Close");
45 
46   gtk_box_append (GTK_BOX (boxh), dmy1);
47   gtk_box_append (GTK_BOX (boxh), btnn);
48   gtk_box_append (GTK_BOX (boxh), btno);
49   gtk_box_append (GTK_BOX (boxh), dmy2);
50   gtk_box_append (GTK_BOX (boxh), btns);
51   gtk_box_append (GTK_BOX (boxh), btnc);
52   gtk_box_append (GTK_BOX (boxh), dmy3);
53 
54   nb = gtk_notebook_new ();
55   gtk_widget_set_hexpand (nb, TRUE);
56   gtk_widget_set_vexpand (nb, TRUE);
57   gtk_box_append (GTK_BOX (boxv), nb);
58 
59   for (i = 0; i < n_files; i++) {
60     if (g_file_load_contents (files[i], NULL, &contents, &length, NULL, NULL)) {
61       scr = gtk_scrolled_window_new ();
62       tv = tfe_text_view_new ();
63       tb = gtk_text_view_get_buffer (GTK_TEXT_VIEW (tv));
64       gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (tv), GTK_WRAP_WORD_CHAR);
65       gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (scr), tv);
66 
67       tfe_text_view_set_file (TFE_TEXT_VIEW (tv),  g_file_dup (files[i]));
68       gtk_text_buffer_set_text (tb, contents, length);
69       g_free (contents);
70       filename = g_file_get_basename (files[i]);
71       lab = gtk_label_new (filename);
72       gtk_notebook_append_page (GTK_NOTEBOOK (nb), scr, lab);
73       nbp = gtk_notebook_get_page (GTK_NOTEBOOK (nb), scr);
74       g_object_set (nbp, "tab-expand", TRUE, NULL);
75       g_free (filename);
76     } else if ((filename = g_file_get_path (files[i])) != NULL) {
77         g_print ("No such file: %s.\n", filename);
78         g_free (filename);
79     } else
80         g_print ("No valid file is given\n");
81   }
82   if (gtk_notebook_get_n_pages (GTK_NOTEBOOK (nb)) > 0) {
83     gtk_window_present (GTK_WINDOW (win));
84   } else
85     gtk_window_destroy (GTK_WINDOW (win));
86 }

函数app_open在主应用程序窗口中构建构件。

  • 25-27:创建一个GtkApplicationWindow实例,并设置标题和默认大小。
  • 29-30:创建GtkBox实例boxv。它是一个垂直框,是GtkApplicationWindow的一个子构件。boxv有两个子构件。第一个子构件是一个水平的boxh。第二个构件是一个GtkNotebook。
  • 32-33:创建一个GtkBox实例boxh,并将其作为第一个子构件附加到boxv中。
  • 35-40:创建3个假标签。标签dmy1和dmy3的字符宽度为10。另一个标签dmy2具有hexpand属性,该属性被设置为TRUE。这使得标签尽可能地水平扩展。
  • 41-44:创建四个按钮。
  • 46-52:添加这些GtkLabel和GtkButton到boxh。
  • 54-57:创建一个gtnotebook实例,并设置hexpand和vexpand属性为TRUE。这使得它在水平和垂直方向上尽可能扩展。它作为第二个子构件添加到boxv中。

构件件构建行的数量是33(=57-25+1)。我们还需要许多变量(boxv、boxh、dmy1等),其中大多数只用于构建窗口组件。有什么好的解决方案来减少这些工作吗?

Gtk提供GtkBuilder。它读取用户界面(UI)数据并构建窗口。它减少了这种繁琐的工作。

2 The UI File

Look at the UI file tfe3.ui that defines widget structure.

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <interface>
 3   <object class="GtkApplicationWindow" id="win">
 4     <property name="title">file editor</property>
 5     <property name="default-width">600</property>
 6     <property name="default-height">400</property>
 7     <child>
 8       <object class="GtkBox" id="boxv">
 9         <property name="orientation">GTK_ORIENTATION_VERTICAL</property>
10         <child>
11           <object class="GtkBox" id="boxh">
12             <property name="orientation">GTK_ORIENTATION_HORIZONTAL</property>
13             <child>
14               <object class="GtkLabel" id="dmy1">
15                 <property name="width-chars">10</property>
16               </object>
17             </child>
18             <child>
19               <object class="GtkButton" id="btnn">
20                 <property name="label">New</property>
21               </object>
22             </child>
23             <child>
24               <object class="GtkButton" id="btno">
25                 <property name="label">Open</property>
26               </object>
27             </child>
28             <child>
29               <object class="GtkLabel" id="dmy2">
30                 <property name="hexpand">TRUE</property>
31               </object>
32             </child>
33             <child>
34               <object class="GtkButton" id="btns">
35                 <property name="label">Save</property>
36               </object>
37             </child>
38             <child>
39               <object class="GtkButton" id="btnc">
40                 <property name="label">Close</property>
41               </object>
42             </child>
43             <child>
44               <object class="GtkLabel" id="dmy3">
45                 <property name="width-chars">10</property>
46               </object>
47             </child>
48           </object>
49         </child>
50         <child>
51           <object class="GtkNotebook" id="nb">
52             <property name="hexpand">TRUE</property>
53             <property name="vexpand">TRUE</property>
54           </object>
55         </child>
56       </object>
57     </child>
58   </object>
59 </interface>

是一个XML文件。标签以<开始,以>结束。标签有两种类型:开始标签和结束标签。例如,<interface>是开始标签,</interface>是结束标签。UI文件以interface标签开始和结束。有些标签,例如对象标签,可以在其开始标签中具有class和id属性。

  • 1: XML声明。它指定XML版本为1.0,编码为UTF-8。
  • 3-6:一个带有GtkApplicationWindow类和id=win的对象标签。这是顶层窗口。并定义了窗口的三个属性。title属性是"file editor", default-width属性是600,default-height属性是400。
  • 7:child标签意味着子构件。例如,第7行告诉我们,id属性为"boxv"的GtkBox对象是win的一个子构件。

比较这个ui文件和tfe2.c源代码中的第25 ~ 57行。两者都使用其后代构件构建相同的窗口。

你可以使用gtk4-builder-tool检查ui文件。

  • gtk4-builder-tool validate <ui file name>对ui文件进行验证。如果ui文件包含一些语法错误,gtk4-builder-tool会打印出错误。
  • gtk4-builder-tool simplify <ui file name>简化ui文件并打印结果。如果指定了--replace选项,它会将ui文件替换为简化的文件。如果ui文件指定了一个属性值,但它是默认值,那么它将被删除。有些值被简化了。例如,“TRUE"和"FALSE"分别变成了"1"和"0”。然而,“TRUE或“FALSE”更利于维护。

在编译之前检查你的ui文件是个好主意。

3 GtkBuilder

GtkBuilder基于ui文件建造构件。

GtkBuilder *build;

build = gtk_builder_new_from_file ("tfe3.ui");
win = GTK_WIDGET (gtk_builder_get_object (build, "win"));
gtk_window_set_application (GTK_WINDOW (win), GTK_APPLICATION (app));
nb = GTK_WIDGET (gtk_builder_get_object (build, "nb"));

函数gtk_builder_new_from_file读取作为参数给出的文件。然后,它构建小构件并创建GtkBuilder对象。函数gtk_builder_get_object (build, “win”)返回指向属性name=win的指针,也就是ui文件中的id。所有部件都是基于ui文件中描述的父子关系连接的。对于下面的程序,我们只需要win和nb。这减少了C源文件中的行数。

$ cd tfe; diff tfe2.c tfe3.c
58a59
>   GtkBuilder *build;
60,103c61,65
<   GtkWidget *boxv;
<   GtkWidget *boxh;
<   GtkWidget *dmy1;
<   GtkWidget *dmy2;
<   GtkWidget *dmy3;
<   GtkWidget *btnn; /* button for new */
<   GtkWidget *btno; /* button for open */
<   GtkWidget *btns; /* button for save */
<   GtkWidget *btnc; /* button for close */
< 
<   win = gtk_application_window_new (GTK_APPLICATION (app));
<   gtk_window_set_title (GTK_WINDOW (win), "file editor");
<   gtk_window_set_default_size (GTK_WINDOW (win), 600, 400);
< 
<   boxv = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
<   gtk_window_set_child (GTK_WINDOW (win), boxv);
< 
<   boxh = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
<   gtk_box_append (GTK_BOX (boxv), boxh);
< 
<   dmy1 = gtk_label_new(NULL); /* dummy label for left space */
<   gtk_label_set_width_chars (GTK_LABEL (dmy1), 10);
<   dmy2 = gtk_label_new(NULL); /* dummy label for center space */
<   gtk_widget_set_hexpand (dmy2, TRUE);
<   dmy3 = gtk_label_new(NULL); /* dummy label for right space */
<   gtk_label_set_width_chars (GTK_LABEL (dmy3), 10);
<   btnn = gtk_button_new_with_label ("New");
<   btno = gtk_button_new_with_label ("Open");
<   btns = gtk_button_new_with_label ("Save");
<   btnc = gtk_button_new_with_label ("Close");
< 
<   gtk_box_append (GTK_BOX (boxh), dmy1);
<   gtk_box_append (GTK_BOX (boxh), btnn);
<   gtk_box_append (GTK_BOX (boxh), btno);
<   gtk_box_append (GTK_BOX (boxh), dmy2);
<   gtk_box_append (GTK_BOX (boxh), btns);
<   gtk_box_append (GTK_BOX (boxh), btnc);
<   gtk_box_append (GTK_BOX (boxh), dmy3);
< 
<   nb = gtk_notebook_new ();
<   gtk_widget_set_hexpand (nb, TRUE);
<   gtk_widget_set_vexpand (nb, TRUE);
<   gtk_box_append (GTK_BOX (boxv), nb);
< 
---
>   build = gtk_builder_new_from_file ("tfe3.ui");
>   win = GTK_WIDGET (gtk_builder_get_object (build, "win"));
>   gtk_window_set_application (GTK_WINDOW (win), GTK_APPLICATION (app));
>   nb = GTK_WIDGET (gtk_builder_get_object (build, "nb"));
>   g_object_unref(build);
138c100
<   app = gtk_application_new ("com.github.ToshioCP.tfe2", G_APPLICATION_HANDLES_OPEN);
---
>   app = gtk_application_new ("com.github.ToshioCP.tfe3", G_APPLICATION_HANDLES_OPEN);
144a107
> 

60,103c61,65表示44(=103-60+1)行更改为5(=65-61+1)行。因此,减少了39行代码。使用ui文件不仅缩短了C源文件的长度,而且使部件的结构更加清晰。

现在我将展示C文件tfe3.c中的app_open函数。

 1 static void
 2 app_open (GApplication *app, GFile ** files, gint n_files, gchar *hint) {
 3   GtkWidget *win;
 4   GtkWidget *nb;
 5   GtkWidget *lab;
 6   GtkNotebookPage *nbp;
 7   GtkWidget *scr;
 8   GtkWidget *tv;
 9   GtkTextBuffer *tb;
10   char *contents;
11   gsize length;
12   char *filename;
13   int i;
14   GtkBuilder *build;
15 
16   build = gtk_builder_new_from_file ("tfe3.ui");
17   win = GTK_WIDGET (gtk_builder_get_object (build, "win"));
18   gtk_window_set_application (GTK_WINDOW (win), GTK_APPLICATION (app));
19   nb = GTK_WIDGET (gtk_builder_get_object (build, "nb"));
20   g_object_unref(build);
21   for (i = 0; i < n_files; i++) {
22     if (g_file_load_contents (files[i], NULL, &contents, &length, NULL, NULL)) {
23       scr = gtk_scrolled_window_new ();
24       tv = tfe_text_view_new ();
25       tb = gtk_text_view_get_buffer (GTK_TEXT_VIEW (tv));
26       gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (tv), GTK_WRAP_WORD_CHAR);
27       gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (scr), tv);
28 
29       tfe_text_view_set_file (TFE_TEXT_VIEW (tv),  g_file_dup (files[i]));
30       gtk_text_buffer_set_text (tb, contents, length);
31       g_free (contents);
32       filename = g_file_get_basename (files[i]);
33       lab = gtk_label_new (filename);
34       gtk_notebook_append_page (GTK_NOTEBOOK (nb), scr, lab);
35       nbp = gtk_notebook_get_page (GTK_NOTEBOOK (nb), scr);
36       g_object_set (nbp, "tab-expand", TRUE, NULL);
37       g_free (filename);
38     } else if ((filename = g_file_get_path (files[i])) != NULL) {
39         g_print ("No such file: %s.\n", filename);
40         g_free (filename);
41     } else
42         g_print ("No valid file is given\n");
43   }
44   if (gtk_notebook_get_n_pages (GTK_NOTEBOOK (nb)) > 0) {
45     gtk_window_present (GTK_WINDOW (win));
46   } else
47     gtk_window_destroy (GTK_WINDOW (win));
48 }

tfe3.c的整个源代码保存在目录src/tfe中。

4 使用ui字符串

GtkBuilder可以使用字符串建立构件。使用gtk_builder_new_from_string而不是gtk_builder_new_from_file。

char *uistring;

uistring =
"<interface>"
  "<object class="GtkApplicationWindow" id="win">"
    "<property name=\"title\">file editor</property>"
    "<property name=\"default-width\">600</property>"
    "<property name=\"default-height\">400</property>"
    "<child>"
      "<object class=\"GtkBox\" id=\"boxv\">"
        "<property name="orientation">GTK_ORIENTATION_VERTICAL</property>"
... ... ...
... ... ...
"</interface>";

build = gtk_builder_new_from_string (uistring, -1);

这种方法有利有弊。这样做的好处是ui字符串是在源代码中编写的。因此,在运行时不需要ui文件。缺点是编写C字符串有点麻烦,因为有双引号。如果你想使用这个方法,你应该写一个脚本来把ui文件转换成C-string。

  • 在每个双引号之前添加反斜杠。
  • 在每行字符串的左右分别添加双引号。

5 Gresource

使用Gresource类似于使用string。但是Gresource是压缩的二进制数据,而不是文本数据。还有一个编译器可以将ui文件编译为Gresource。它不仅可以编译文本文件,还可以编译图像、声音等二进制文件。在编译之后,它将它们打包成一个Gresource对象。

resource编译器glib-compile-resources需要一个xml文件。它描述了资源文件。

1 <?xml version="1.0" encoding="UTF-8"?>
2 <gresources>
3   <gresource prefix="/com/github/ToshioCP/tfe3">
4     <file>tfe3.ui</file>
5   </gresource>
6 </gresources>
  • 2: gresources标签可以包含多个gresources (gresource标签)。然而,这个xml只有一个gresource。
  • 3: gresource的前缀为/com/github/ToshioCP/tfe3。
  • 4: gresource的名字是tfe3.ui。资源指向/com/github/ToshioCP/tfe3/tfe3。ui由GtkBuilder。模式是“prefix”+“name”。如果想添加更多文件,请将它们插入第4行和第5行之间。

将这个xml文本保存到tfe3.gresource.xml。gresource编译器glib-compile-resources通过参数 --help显示其用法。

$ LANG=C glib-compile-resources --help
Usage:
  glib-compile-resources [OPTION?] FILE

Compile a resource specification into a resource file.
Resource specification files have the extension .gresource.xml,
and the resource file have the extension called .gresource.

Help Options:
  -h, --help                   Show help options

Application Options:
  --version                    Show program version and exit
  --target=FILE                Name of the output file
  --sourcedir=DIRECTORY        The directories to load files referenced in FILE from (default: current directory)
  --generate                   Generate output in the format selected for by the target filename extension
  --generate-header            Generate source header
  --generate-source            Generate source code used to link in the resource file into your code
  --generate-dependencies      Generate dependency list
  --dependency-file=FILE       Name of the dependency file to generate
  --generate-phony-targets     Include phony targets in the generated dependency file
  --manual-register            Don?t automatically create and register resource
  --internal                   Don?t export functions; declare them G_GNUC_INTERNAL
  --external-data              Don?t embed resource data in the C file; assume it's linked externally instead
  --c-name                     C identifier name used for the generated source code
  -C, --compiler               The target C compiler (default: the CC environment variable)

现在运行编译器。

$ glib-compile-resources tfe3.gresource.xml --target=resources.c --generate-source

然后生成一个C源文件resources.c。修改tfe3.c,并保存为tfe3_r.c。

#include "resources.c"
... ... ...
... ... ...
build = gtk_builder_new_from_resource ("/com/github/ToshioCP/tfe3/tfe3.ui");
... ... ...
... ... ...

函数gtk_builder_new_from_resource从resource构建小部件。

然后,编译并运行它。出现一个窗口,它与本页开始时的截图相同。

一般来说,resource是C语言最好的表达方式。如果您使用其他语言,如Ruby, string比resource更好。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【年度总结】2022不忘初心,砥砺前行 2023纵有疾风起,人生不言弃。

2022 工作 砥砺前行 跨境电商跑路 2022年3月&#xff0c;从一家小跨境电商被动跑路&#xff0c;果断处于迷茫期&#xff0c;被动跑路的最好优势就是有赔偿&#xff0c;哈哈&#xff0c;怎么还有一丢丢高兴呢。简单总结了下在该公司的经历&#xff0c;是之前的老大带我去的&am…

如何通过产品帮助中心减轻客服压力,提高内部人员工作效率

客户的问题一直在重复&#xff0c;客服人员压力山大 客户不愿接听客服电话&#xff0c;产品问题难以解决 下班时间休息日&#xff0c;产品问题找谁问&#xff1f; 这些关于客户服务的老问题们困扰着许多产品方多年 要解决以上问题&#xff0c;更好地满足顾客需求。 搭建帮…

基于javaweb(springboot+mybatis)生活美食分享平台管理系统设计和实现以及文档报告

基于javaweb(springbootmybatis)生活美食分享平台管理系统设计和实现以及文档报告 博主介绍&#xff1a;5年java开发经验&#xff0c;专注Java开发、定制、远程、文档编写指导等,csdn特邀作者、专注于Java技术领域 作者主页 超级帅帅吴 Java毕设项目精品实战案例《500套》 欢迎…

详解函数指针(●‘◡‘●)☞

本文紧接于http://t.csdn.cn/78wbF 这篇一.函数指针数组\ ( >O< ) /1.书写形式&#xff1a;由函数指针内部*变量名>*变量名[n]&#xff1b; 2.使用&#xff1a;函数指针数组的用途&#xff1a;转移表 例如&#xff1a;模拟计算器&#xff1a;#include<stdio.h> …

用了这么久 IDEA,你还没用过 Live Templates 吗?

大家好&#xff0c;我是风筝&#xff0c;公众号「古时的风筝」&#xff0c;专注于 Java技术 及周边生态。 Live Templates 是什么&#xff0c;听上去感觉挺玄乎的。有的同学用过之后觉得简直太好用了&#xff0c;不能说大大提高了开发效率吧&#xff0c;至少也是小小的提高一下…

Qt创建项目:手把手创建第一个Qt项目

上一节介绍了QtCreator编辑器的页面长什么样子&#xff0c;以及都有哪些功能区&#xff0c;每个功能区都是用来做什么的。这一节我就手把手带大家创建一个Qt项目。 创建项目 点击新建按钮 创建项目有两个入口&#xff0c;一个是在欢迎页面的projects中点击New(新建)按钮&…

未来,勒索软件会呈现何种发展态势?

尽管过去一年里&#xff0c;全世界大约花费了1500亿美元在网络安全领域上&#xff0c;却无法真正阻止黑客攻击。在过去一年里&#xff0c;针对医院、学校、政府的勒索软件越来越多&#xff1b;加密货币领域也有无休止的黑客盗窃事件&#xff1b;还有针对微软、英伟达、Rockstar…

CORS跨域通信

在上一集的坐牢文章中&#xff0c;我们介绍了非官方的很多中方案&#xff0c;其中不乏一些江湖秘术。今天的这个&#xff0c;绝对的正统&#xff0c;纯正的官方打造。我们赶紧来看看。 1.什么是CORS&#xff1f; CORS 是一个 W3C 标准&#xff0c;全称是“跨域资源共享”&…

Prometheus的使用

Prometheus 是一个开放性的监控解决方案&#xff0c;用户可以非常方便的安装和使用 Prometheus 并且能够非常方便的对其进行扩展。 在Prometheus的架构设计中&#xff0c;Prometheus Server 并不直接服务监控特定的目标&#xff0c;其主要任务负责数据的收集&#xff0c;存储并…

ArcGIS Engine基础(31)之使用仿射变换对矢量数据进行空间校正

在生产数据过程中&#xff0c;因每个工程项目都可能有自己的施工坐标系&#xff0c;难免会产生数据提供方与数据使用方采用的坐标系不一致&#xff0c;造成数据在不同坐标系下存在一定偏移、旋转、缩放等&#xff0c;为了让数据能够在新坐标系准确定位&#xff0c;需要进行空间…

kitti数据集理解及可视化

kitti数据集简介 kitti数据集是比较早出来的3D检测方面的数据集&#xff0c;相对来说数据结构简单&#xff0c;适合做单目检测的工作&#xff0c;目前也是业界和学术界常用的公开数据集。 自己最近也在做单目3D检测的工作&#xff0c;所以也分享一些理解&#xff0c;希望能给到…

微服务自动化管理【Docker跨主机集群之Flannel】

环境说明 CentOS7 etcd-v3.4.3-linux-amd64.tar.gz flannel-v0.11.0-linux-amd64.tar.gz 官方文档&#xff1a;https://github.com/coreos/flannel 下载地址&#xff1a;https://github.com/coreos/flannel/releases/download/v0.11.0/flannel-v0.11.0-linux-amd64.tar.gz 1.…

verilog学习笔记- 9)流水灯实验

目录 简介&#xff1a; 实验任务&#xff1a; 硬件设计&#xff1a; 程序设计&#xff1a; 下载验证&#xff1a; 简介&#xff1a; LED&#xff0c;又名发光二极管。LED 灯工作电流很小&#xff08;有的仅零点几毫安即可发光&#xff09;&#xff0c;抗冲击和抗震性能好&…

工业互联网安全漏洞分析

声明 本文是学习github5.com 网站的报告而整理的学习笔记,分享出来希望更多人受益,如果存在侵权请及时联系我们 研究背景 在政策与技术的双轮驱动下&#xff0c;工业控制系统正在越来越多地与企业内网和互联网相连接&#xff0c;并与新型服务模式相结合&#xff0c;逐步形成…

day01--Python学习笔记之安装及测试

目录 官网下载 1、Python自带简单的开发环境 2、Python的交互式命令行程序 3、官方技术文档 4、安装模块文档 1、Python自带简单的开发环境 在当前中编辑代码 在新文件中编辑代码 2、P…

springboot 使用tomcat详解

1.使用内嵌tomcat启动 创建tomcat对象设置端口设置Context设置servlet 和 路径 2.spring中单独注册servlet和地址的映射关系 Beanpublic ServletRegistrationBean getServletRegistrationBean() {ServletRegistrationBean bean new ServletRegistrationBean(apiServlet);bean…

免费GPU攻略

白嫖kaggle kaggle每周会送38个小时&#xff0c;16GB显存。 验证手机号 根据 kaggle问答可知&#xff0c;需要手机号短信验证&#xff0c;账号才能用GPU。国内的手机号都是可用的。操作如下&#xff1a; 点击右上角头像&#xff0c;点击Account。 到了个人详情页后&#xf…

基于JAVA springboot+mybatis智慧生活分享平台设计和实现

基于JAVA springbootmybatis智慧生活分享平台设计和实现 博主介绍&#xff1a;5年java开发经验&#xff0c;专注Java开发、定制、远程、文档编写指导等,csdn特邀作者、专注于Java技术领域 作者主页 超级帅帅吴 Java毕设项目精品实战案例《500套》 欢迎点赞 收藏 ⭐留言 文末获取…

【MySQL进阶】执行一条 sql 语句,期间会发生什么

【MySQL进阶】执行一条 sql 语句&#xff0c;期间会发生什么? 文章目录【MySQL进阶】执行一条 sql 语句&#xff0c;期间会发生什么?MySQL 执行流程是怎样的&#xff1f;第一步&#xff1a;连接器第二步&#xff1a;查询缓存第三步&#xff1a;解析 SQL解析器第四步&#xff…

Google Play Install Referrer API 和 Facebook App Ads Referral 集成

介绍&#xff1a;由于需要精准的获取投放广告的数据&#xff08;投放的平台&#xff0c;防止数据的丢失等&#xff09;。我们使用了Google Play Install Referrer API 和Facebook App Ads Referral结合采集数据&#xff0c;然后通过后台服务记录数据。最后服务器记录的数据与Fa…