modified section two to three.

This commit is contained in:
Toshio Sekiya 2021-01-05 10:41:29 +09:00
parent 49055b1cb6
commit 2788a3712b
12 changed files with 79 additions and 72 deletions

1
.gitignore vendored
View file

@ -5,6 +5,7 @@ makehtml.rb
pickoutfunc.rb
src/img.rb
src/toi.rb
src/misc/a.out
# backup file
*~

View file

@ -33,7 +33,7 @@ def src2md srcmd, md
c_functions.each do |c_function|
from = c_file_buf.find_index { |line| line =~ /^#{c_function} *\(/ }
if ! from
warn "ERROR!!! --- Didn't find #{func} in #{filename}. ---"
warn "ERROR!!! --- Didn't find #{c_function} in #{filename}. ---"
break
end
to = from

View file

@ -616,5 +616,5 @@ The followings are the source files of tfe5.
218 622 7454 tfe5/tfetextview.c
29 47 545 tfe5/tfetextview.h
64 105 2266 tfe5/tfe.ui
574 1482 17411 合計
574 1482 17411 total
Up: [Readme.md](Readme.md), Prev: [Section 13](sec13.md), Next: [Section 15](sec15.md)

26
sec2.md
View file

@ -33,18 +33,18 @@ The following is the C code representing the scenario above.
12 }
13
The first line says that this program includes the GTK header libraries.
The first line says that this program includes the header files of the Gtk libraries.
The function `main` above is a startup function in C language.
The variable `app` is defined as a pointer to GtkApplication, which is actually a structure in which information about the application is stored.
The function `gtk_application_new` generates a GtkApplication and sets its pointer to `app`.
The function `gtk_application_new` generates a GtkApplication object and sets its pointer to `app`.
The meaning of the arguments will be explained later.
The function `g_application_run` invokes the GtkApplication pointed by `app`.
The function `g_application_run` invokes the GtkApplication object pointed by `app`.
(We often say that the function invokes `app`.
Actually, `app` is not an object but an pointer to the object.
However, it is simple and short, and probably no confusion occurs.)
To compile this, the following command needs to be run.
The string pr1.c is the filename of the C source code.
The string pr1.c is the filename of the C source code above.
$ gcc `pkg-config --cflags gtk4` pr1.c `pkg-config --libs gtk4`
@ -58,7 +58,7 @@ Let's run it.
Oh, just an error message.
But this error message means that the GtkApplication object ran without a doubt.
Now, think about the message in the next section.
Now, think about the message in the next subsection.
### signal
@ -66,9 +66,9 @@ The message tells us that:
1. The application GtkApplication doesn't implement `g_application_activate()`.
2. And it has no handlers connected to the activate signal.
3. You need to solve at least one of this.
3. You need to solve at least one of these.
These two cause of the error are related to signals.
These two causes of the error are related to signals.
So, I will explain it to you first.
Signal is emitted when something happens.
@ -132,8 +132,9 @@ The handler function is described in that subsection.
In addition, `g_signal_connect` is described in GObject API reference.
API reference is very important.
You should see and understand it to write GTK applications.
They are located in ['GNOME Developer Center'](https://developer.gnome.org/).
Let's compile the source file `pr2.c` above and run it.
Let's compile the source file above (`pr2.c`) and run it.
$ gcc `pkg-config --cflags gtk4` pr2.c `pkg-config --libs gtk4`
$ ./a.out
@ -143,14 +144,14 @@ Let's compile the source file `pr2.c` above and run it.
OK, well done.
However, you may have noticed that it's painful to type such a long line to compile.
It is a good idea to use shell script to solve this problem.
Make a text file which contains the following text.
Make a text file which contains the following line.
gcc `pkg-config --cflags gtk4` $1.c `pkg-config --libs gtk4`
Then, save it in $HOME/bin, which is usually /home/(username)/bin.
Then, save it under the directory $HOME/bin, which is usually /home/(username)/bin.
(If your user name is James, then the directory is /home/james/bin).
And turn on the execute bit of the file.
Suppose the filename is comp, then the procedure is as follows.
Suppose the filename is `comp`, then the procedure is as follows.
$ chmod 755 $HOME/bin/comp
$ ls -log $HOME/bin
@ -231,7 +232,7 @@ You need to cast `win` to GtkWindow and `app` to GtkApplication.
`GTK_WINDOW` and `GTK_APPLICATION` macro is appropriate for that.
GtkApplication continues to run until the related window is destroyed.
If you didn't connect GtkWindow and GtkApplication, GtkApplication shutdowns soon.
If you didn't connect GtkWindow and GtkApplication, GtkApplication shutdowns immediately.
Because no window is connected to GtkApplication, it doesn't need to wait anything.
As it shutdowns the generated window is also destroyed.
@ -281,5 +282,4 @@ The program sets the title and the default size of the window.
Compile it and run `a.out`, then you will see a bigger window with its title "pr4".
![Screenshot of the window](image/screenshot_pr4.png)
Up: [Readme.md](Readme.md), Prev: [Section 1](sec1.md), Next: [Section 3](sec3.md)

48
sec3.md
View file

@ -5,7 +5,7 @@ Up: [Readme.md](Readme.md), Prev: [Section 2](sec2.md), Next: [Section 4](sec4.
### GtkLabel
We made an window and show it on the screen in the previous chapter.
We made an window and show it on the screen in the previous section.
Now we go on to the next topic, widgets in the window.
The simplest widget is GtkLabel.
It is a widget with a string in it.
@ -18,7 +18,7 @@ It is a widget with a string in it.
6 GtkWidget *lab;
7
8 win = gtk_application_window_new (GTK_APPLICATION (app));
9 gtk_window_set_title (GTK_WINDOW (win), "lb4");
9 gtk_window_set_title (GTK_WINDOW (win), "lb1");
10 gtk_window_set_default_size (GTK_WINDOW (win), 400, 300);
11
12 lab = gtk_label_new ("Hello.");
@ -53,13 +53,13 @@ A window with a message "Hello." appears.
There's only a little change between `pr4.c` and `lb1.c`.
Diff is a good program to know the difference between two files.
$ diff misc/pr4.c lb1.c
$ cd misc; diff pr4.c lb1.c
5a6
> GtkWidget *lab;
8c9
< gtk_window_set_title (GTK_WINDOW (win), "pr4");
---
> gtk_window_set_title (GTK_WINDOW (win), "lb4");
> gtk_window_set_title (GTK_WINDOW (win), "lb1");
9a11,14
>
> lab = gtk_label_new ("Hello.");
@ -102,7 +102,7 @@ The following program shows how to catch the signal and do something.
1 #include <gtk/gtk.h>
2
3 static void
4 on_clicked (GtkButton *btn, gpointer user_data) {
4 click_cb (GtkButton *btn, gpointer user_data) {
5 g_print ("Clicked.\n");
6 }
7
@ -112,12 +112,12 @@ The following program shows how to catch the signal and do something.
11 GtkWidget *btn;
12
13 win = gtk_application_window_new (GTK_APPLICATION (app));
14 gtk_window_set_title (GTK_WINDOW (win), "lb4");
14 gtk_window_set_title (GTK_WINDOW (win), "lb2");
15 gtk_window_set_default_size (GTK_WINDOW (win), 400, 300);
16
17 btn = gtk_button_new_with_label ("Click me");
18 gtk_window_set_child (GTK_WINDOW (win), btn);
19 g_signal_connect (btn, "clicked", G_CALLBACK (on_clicked), NULL);
19 g_signal_connect (btn, "clicked", G_CALLBACK (click_cb), NULL);
20
21 gtk_widget_show (win);
22 }
@ -138,8 +138,9 @@ The following program shows how to catch the signal and do something.
Look at the line 17 to 19.
First, generate a GtkButton widget `btn` with a label "Click me".
Then, set it to the window `win` as a child.
Finally, connect a "clicked" signal of the button to a handler (function) `on_click`.
So, if `btn` is clicked, the function `on_click` is invoked.
Finally, connect a "clicked" signal of the button to a handler (function) `click_cb`.
So, if `btn` is clicked, the function `click_cb` is invoked.
The suffix cb means "call back".
Name the program `lb2.c` and save it.
Now compile and run it.
@ -156,7 +157,7 @@ So, we will change the handler.
The following code is `lb3.c`.
1 static void
2 on_clicked (GtkButton *btn, gpointer user_data) {
2 click_cb (GtkButton *btn, gpointer user_data) {
3 GtkWindow *win = GTK_WINDOW (user_data);
4 gtk_window_destroy (win);
5 }
@ -167,36 +168,42 @@ The following code is `lb3.c`.
10 GtkWidget *btn;
11
12 win = gtk_application_window_new (GTK_APPLICATION (app));
13 gtk_window_set_title (GTK_WINDOW (win), "lb4");
13 gtk_window_set_title (GTK_WINDOW (win), "lb3");
14 gtk_window_set_default_size (GTK_WINDOW (win), 400, 300);
15
16 btn = gtk_button_new_with_label ("Quit");
17 gtk_window_set_child (GTK_WINDOW (win), btn);
18 g_signal_connect (btn, "clicked", G_CALLBACK (on_clicked), win);
18 g_signal_connect (btn, "clicked", G_CALLBACK (click_cb), win);
19
20 gtk_widget_show (win);
21 }
And the difference between `lb2.c` and `lb3.c` is as follows.
$ diff lb2.c lb3.c
$ cd misc; diff lb2.c lb3.c
5c5,6
< g_print ("Clicked.\n");
---
> GtkWindow *win = GTK_WINDOW (user_data);
> gtk_window_destroy (win);
14c15
< gtk_window_set_title (GTK_WINDOW (win), "lb2");
---
> gtk_window_set_title (GTK_WINDOW (win), "lb3");
17c18
< btn = gtk_button_new_with_label ("Click me");
---
> btn = gtk_button_new_with_label ("Quit");
19c20
< g_signal_connect (btn, "clicked", G_CALLBACK (on_clicked), NULL);
< g_signal_connect (btn, "clicked", G_CALLBACK (click_cb), NULL);
---
> g_signal_connect (btn, "clicked", G_CALLBACK (on_clicked), win);
> g_signal_connect (btn, "clicked", G_CALLBACK (click_cb), win);
29c30
< app = gtk_application_new ("com.github.ToshioCP.lb2", G_APPLICATION_FLAGS_NONE);
---
> app = gtk_application_new ("com.github.ToshioCP.lb3", G_APPLICATION_FLAGS_NONE);
35d35
<
The change is:
@ -232,7 +239,7 @@ Now, code it.
1 #include <gtk/gtk.h>
2
3 static void
4 on_clicked1 (GtkButton *btn, gpointer user_data) {
4 click1_cb (GtkButton *btn, gpointer user_data) {
5 const gchar *s;
6
7 s = gtk_button_get_label (btn);
@ -243,7 +250,7 @@ Now, code it.
12 }
13
14 static void
15 on_clicked2 (GtkButton *btn, gpointer user_data) {
15 click2_cb (GtkButton *btn, gpointer user_data) {
16 GtkWindow *win = GTK_WINDOW (user_data);
17 gtk_window_destroy (win);
18 }
@ -264,10 +271,10 @@ Now, code it.
33 gtk_window_set_child (GTK_WINDOW (win), box);
34
35 btn1 = gtk_button_new_with_label ("Hello.");
36 g_signal_connect (btn1, "clicked", G_CALLBACK (on_clicked1), NULL);
36 g_signal_connect (btn1, "clicked", G_CALLBACK (click1_cb), NULL);
37
38 btn2 = gtk_button_new_with_label ("Quit");
39 g_signal_connect (btn2, "clicked", G_CALLBACK (on_clicked2), win);
39 g_signal_connect (btn2, "clicked", G_CALLBACK (click2_cb), win);
40
41 gtk_box_append (GTK_BOX (box), btn1);
42 gtk_box_append (GTK_BOX (box), btn2);
@ -286,7 +293,6 @@ Now, code it.
55 g_object_unref (app);
56 return stat;
57 }
58
Look at the function `on_activate`.
@ -296,7 +302,7 @@ After the generation of GtkApplicationWindow, GtkBox is generated.
gtk_box_set_homogeneous (GTK_BOX (box), TRUE);
The first argument arranges children vertically.
The second argument is sizes between children.
The second argument is the size between children.
The next function fills a box with children, giving them equal space.
After that, two buttons `btn1` and `btn2` are generated and the signal handlers are set.

1
src/misc/comp Executable file
View file

@ -0,0 +1 @@
gcc `pkg-config --cflags gtk4` $1.c `pkg-config --libs gtk4`

View file

@ -6,7 +6,7 @@ on_activate (GApplication *app, gpointer user_data) {
GtkWidget *lab;
win = gtk_application_window_new (GTK_APPLICATION (app));
gtk_window_set_title (GTK_WINDOW (win), "lb4");
gtk_window_set_title (GTK_WINDOW (win), "lb1");
gtk_window_set_default_size (GTK_WINDOW (win), 400, 300);
lab = gtk_label_new ("Hello.");

View file

@ -1,7 +1,7 @@
#include <gtk/gtk.h>
static void
on_clicked (GtkButton *btn, gpointer user_data) {
click_cb (GtkButton *btn, gpointer user_data) {
g_print ("Clicked.\n");
}
@ -11,12 +11,12 @@ on_activate (GApplication *app, gpointer user_data) {
GtkWidget *btn;
win = gtk_application_window_new (GTK_APPLICATION (app));
gtk_window_set_title (GTK_WINDOW (win), "lb4");
gtk_window_set_title (GTK_WINDOW (win), "lb2");
gtk_window_set_default_size (GTK_WINDOW (win), 400, 300);
btn = gtk_button_new_with_label ("Click me");
gtk_window_set_child (GTK_WINDOW (win), btn);
g_signal_connect (btn, "clicked", G_CALLBACK (on_clicked), NULL);
g_signal_connect (btn, "clicked", G_CALLBACK (click_cb), NULL);
gtk_widget_show (win);
}

View file

@ -1,7 +1,7 @@
#include <gtk/gtk.h>
static void
on_clicked (GtkButton *btn, gpointer user_data) {
click_cb (GtkButton *btn, gpointer user_data) {
GtkWindow *win = GTK_WINDOW (user_data);
gtk_window_destroy (win);
}
@ -12,12 +12,12 @@ on_activate (GApplication *app, gpointer user_data) {
GtkWidget *btn;
win = gtk_application_window_new (GTK_APPLICATION (app));
gtk_window_set_title (GTK_WINDOW (win), "lb4");
gtk_window_set_title (GTK_WINDOW (win), "lb3");
gtk_window_set_default_size (GTK_WINDOW (win), 400, 300);
btn = gtk_button_new_with_label ("Quit");
gtk_window_set_child (GTK_WINDOW (win), btn);
g_signal_connect (btn, "clicked", G_CALLBACK (on_clicked), win);
g_signal_connect (btn, "clicked", G_CALLBACK (click_cb), win);
gtk_widget_show (win);
}
@ -33,4 +33,3 @@ main (int argc, char **argv) {
g_object_unref (app);
return stat;
}

View file

@ -1,7 +1,7 @@
#include <gtk/gtk.h>
static void
on_clicked1 (GtkButton *btn, gpointer user_data) {
click1_cb (GtkButton *btn, gpointer user_data) {
const gchar *s;
s = gtk_button_get_label (btn);
@ -12,7 +12,7 @@ on_clicked1 (GtkButton *btn, gpointer user_data) {
}
static void
on_clicked2 (GtkButton *btn, gpointer user_data) {
click2_cb (GtkButton *btn, gpointer user_data) {
GtkWindow *win = GTK_WINDOW (user_data);
gtk_window_destroy (win);
}
@ -33,10 +33,10 @@ on_activate (GApplication *app, gpointer user_data) {
gtk_window_set_child (GTK_WINDOW (win), box);
btn1 = gtk_button_new_with_label ("Hello.");
g_signal_connect (btn1, "clicked", G_CALLBACK (on_clicked1), NULL);
g_signal_connect (btn1, "clicked", G_CALLBACK (click1_cb), NULL);
btn2 = gtk_button_new_with_label ("Quit");
g_signal_connect (btn2, "clicked", G_CALLBACK (on_clicked2), win);
g_signal_connect (btn2, "clicked", G_CALLBACK (click2_cb), win);
gtk_box_append (GTK_BOX (box), btn1);
gtk_box_append (GTK_BOX (box), btn2);
@ -55,4 +55,3 @@ main (int argc, char **argv) {
g_object_unref (app);
return stat;
}

View file

@ -20,18 +20,18 @@ The following is the C code representing the scenario above.
@@@ misc/pr1.c
The first line says that this program includes the GTK header libraries.
The first line says that this program includes the header files of the Gtk libraries.
The function `main` above is a startup function in C language.
The variable `app` is defined as a pointer to GtkApplication, which is actually a structure in which information about the application is stored.
The function `gtk_application_new` generates a GtkApplication and sets its pointer to `app`.
The function `gtk_application_new` generates a GtkApplication object and sets its pointer to `app`.
The meaning of the arguments will be explained later.
The function `g_application_run` invokes the GtkApplication pointed by `app`.
The function `g_application_run` invokes the GtkApplication object pointed by `app`.
(We often say that the function invokes `app`.
Actually, `app` is not an object but an pointer to the object.
However, it is simple and short, and probably no confusion occurs.)
To compile this, the following command needs to be run.
The string pr1.c is the filename of the C source code.
The string pr1.c is the filename of the C source code above.
$ gcc `pkg-config --cflags gtk4` pr1.c `pkg-config --libs gtk4`
@ -45,7 +45,7 @@ Let's run it.
Oh, just an error message.
But this error message means that the GtkApplication object ran without a doubt.
Now, think about the message in the next section.
Now, think about the message in the next subsection.
### signal
@ -53,9 +53,9 @@ The message tells us that:
1. The application GtkApplication doesn't implement `g_application_activate()`.
2. And it has no handlers connected to the activate signal.
3. You need to solve at least one of this.
3. You need to solve at least one of these.
These two cause of the error are related to signals.
These two causes of the error are related to signals.
So, I will explain it to you first.
Signal is emitted when something happens.
@ -101,8 +101,9 @@ The handler function is described in that subsection.
In addition, `g_signal_connect` is described in GObject API reference.
API reference is very important.
You should see and understand it to write GTK applications.
They are located in ['GNOME Developer Center'](https://developer.gnome.org/).
Let's compile the source file `pr2.c` above and run it.
Let's compile the source file above (`pr2.c`) and run it.
$ gcc `pkg-config --cflags gtk4` pr2.c `pkg-config --libs gtk4`
$ ./a.out
@ -112,14 +113,14 @@ Let's compile the source file `pr2.c` above and run it.
OK, well done.
However, you may have noticed that it's painful to type such a long line to compile.
It is a good idea to use shell script to solve this problem.
Make a text file which contains the following text.
Make a text file which contains the following line.
gcc `pkg-config --cflags gtk4` $1.c `pkg-config --libs gtk4`
Then, save it in $HOME/bin, which is usually /home/(username)/bin.
Then, save it under the directory $HOME/bin, which is usually /home/(username)/bin.
(If your user name is James, then the directory is /home/james/bin).
And turn on the execute bit of the file.
Suppose the filename is comp, then the procedure is as follows.
Suppose the filename is `comp`, then the procedure is as follows.
$ chmod 755 $HOME/bin/comp
$ ls -log $HOME/bin
@ -193,7 +194,7 @@ You need to cast `win` to GtkWindow and `app` to GtkApplication.
`GTK_WINDOW` and `GTK_APPLICATION` macro is appropriate for that.
GtkApplication continues to run until the related window is destroyed.
If you didn't connect GtkWindow and GtkApplication, GtkApplication shutdowns soon.
If you didn't connect GtkWindow and GtkApplication, GtkApplication shutdowns immediately.
Because no window is connected to GtkApplication, it doesn't need to wait anything.
As it shutdowns the generated window is also destroyed.
@ -235,4 +236,3 @@ The program sets the title and the default size of the window.
Compile it and run `a.out`, then you will see a bigger window with its title "pr4".
![Screenshot of the window](../image/screenshot_pr4.png)

View file

@ -4,12 +4,12 @@
### GtkLabel
We made an window and show it on the screen in the previous chapter.
We made an window and show it on the screen in the previous section.
Now we go on to the next topic, widgets in the window.
The simplest widget is GtkLabel.
It is a widget with a string in it.
@@@ lb1.c
@@@ misc/lb1.c
Save this program to a file `lb1.c`.
Then compile and run it.
@ -25,7 +25,7 @@ There's only a little change between `pr4.c` and `lb1.c`.
Diff is a good program to know the difference between two files.
$$$
diff misc/pr4.c lb1.c
cd misc; diff pr4.c lb1.c
$$$
This tells us:
@ -57,13 +57,14 @@ In this subsection, we will make a button with a label.
When a button is clicked on, it emits a "clicked" signal.
The following program shows how to catch the signal and do something.
@@@ lb2.c
@@@ misc/lb2.c
Look at the line 17 to 19.
First, generate a GtkButton widget `btn` with a label "Click me".
Then, set it to the window `win` as a child.
Finally, connect a "clicked" signal of the button to a handler (function) `on_click`.
So, if `btn` is clicked, the function `on_click` is invoked.
Finally, connect a "clicked" signal of the button to a handler (function) `click_cb`.
So, if `btn` is clicked, the function `click_cb` is invoked.
The suffix cb means "call back".
Name the program `lb2.c` and save it.
Now compile and run it.
@ -79,12 +80,12 @@ However, using g_print is out of harmony with GTK which is a GUI library.
So, we will change the handler.
The following code is `lb3.c`.
@@@ lb3.c on_clicked on_activate
@@@ misc/lb3.c click_cb on_activate
And the difference between `lb2.c` and `lb3.c` is as follows.
$$$
diff lb2.c lb3.c
cd misc; diff lb2.c lb3.c
$$$
The change is:
@ -118,7 +119,7 @@ After this, the Widgets are connected as following diagram.
Now, code it.
@@@ lb4.c
@@@ misc/lb4.c
Look at the function `on_activate`.
@ -128,7 +129,7 @@ After the generation of GtkApplicationWindow, GtkBox is generated.
gtk_box_set_homogeneous (GTK_BOX (box), TRUE);
The first argument arranges children vertically.
The second argument is sizes between children.
The second argument is the size between children.
The next function fills a box with children, giving them equal space.
After that, two buttons `btn1` and `btn2` are generated and the signal handlers are set.