Gtk4-tutorial/src/sec4.src.md

151 lines
4.9 KiB
Markdown
Raw Normal View History

# Widgets (1)
2020-12-21 13:12:05 +01:00
## GtkLabel, GtkButton and Gtkbox
2020-12-21 13:12:05 +01:00
### GtkLabel
2020-12-21 13:12:05 +01:00
2021-01-26 14:36:17 +01:00
We made a 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.
2020-12-21 13:12:05 +01:00
@@@include
misc/lb1.c
@@@
2020-12-21 13:12:05 +01:00
Save this program to a file `lb1.c`.
Then compile and run it.
2020-12-21 13:12:05 +01:00
$ comp lb1
$ ./a.out
2020-12-21 13:12:05 +01:00
A window with a message "Hello." appears.
2020-12-21 13:12:05 +01:00
![Screenshot of the label](../image/screenshot_lb1.png){width=6.3cm height=5.325cm}
2020-12-21 13:12:05 +01:00
There's only a little change between `pr4.c` and `lb1.c`.
Diff is a good program to know the difference between two files.
2020-12-21 13:12:05 +01:00
@@@shell
cd misc; diff pr4.c lb1.c
@@@
This tells us:
- The definition of a variable lab is added.
- The title of the window is changed.
- A label is generated and connected to the window.
The function `gtk_window_set_child (GTK_WINDOW (win), lab)` makes the label `lab` a child widget of the window `win`.
Be careful.
A child widget is different from a child object.
Objects have parent-child relationship and Widgets also have parent-child relationship.
But these two relationships are totally different.
Don't be confused.
In the program `lb1.c`, `lab` is a child widget of `win`.
Child widgets are always located inside its parent widget in the screen.
See the window appeared on the screen.
The window includes the label.
2021-01-26 14:36:17 +01:00
The window `win` doesn't have any parents.
We call such a window top-level window.
One application can have two or more top-level windows.
### GtkButton
Next widget is GtkButton.
It has a label or icon on it.
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.
@@@include
misc/lb2.c
@@@
Look at the line 17 to 19.
First, it generates a GtkButton widget `btn` with a label "Click me".
Then, adds the button to the window `win` as a child.
Finally, connects 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.
2020-12-21 13:12:05 +01:00
![Screenshot of the label](../image/screenshot_lb2.png){width=11.205cm height=6.945cm}
A window with the button appears.
Click the button (it is a large button, you can click everywhere inside the window), then a string "Clicked." appears on the shell terminal.
It shows the handler was invoked by clicking the button.
2020-12-21 13:12:05 +01:00
It's fairly good for us to make sure that the clicked signal was caught and the handler was invoked.
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`.
2020-12-21 13:12:05 +01:00
@@@include
misc/lb3.c click_cb on_activate
@@@
2020-12-21 13:12:05 +01:00
And the difference between `lb2.c` and `lb3.c` is as follows.
2020-12-21 13:12:05 +01:00
@@@shell
cd misc; diff lb2.c lb3.c
@@@
2020-12-21 13:12:05 +01:00
The change is:
2020-12-21 13:12:05 +01:00
- The function `g_print` in `lb2.c` was deleted and two lines above are inserted instead.
- The label of `btn` is changed from "Click me" to "Quit".
- The fourth argument of `g_signal_connect` is changed from `NULL` to `win`.
2020-12-21 13:12:05 +01:00
Most important is the fourth argument of `g_signal_connect`.
It is described as "data to pass to handler" in the definition of g\_signal\_connect in GObject API reference.
Therefore, `win` which is a pointer to GtkApplicationWindow is passed to the handler as a second parameter user_data.
Then, the handler cast it to a pointer to GtkWindow and call `gtk_window_destroy` and destroy the top window.
Then, the application quits.
### GtkBox
GtkWindow and GtkApplicationWindow can have only one child.
If you want to add two or more widgets inside a window, you need a container widget.
GtkBox is one of the containers.
It arranges two or more child widgets into a single row or column.
The following procedure shows the way to add two buttons in a window.
- Generate GtkApplicationWindow.
- Generate GtkBox and add it to GtkApplicationWindow as a child.
- Generate GtkButton and append it to GtkBox.
- Generate another GtkButton and append it to GtkBox.
After this, the Widgets are connected as following diagram.
![Parent-child relationship](../image/box.png){width=7.725cm height=2.055cm}
Now, code it.
@@@include
misc/lb4.c
@@@
Look at the function `on_activate`.
After the generation of GtkApplicationWindow, GtkBox is generated.
box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 5);
gtk_box_set_homogeneous (GTK_BOX (box), TRUE);
The first argument arranges children vertically.
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.
Then, these two buttons are appended to the box.
![Screenshot of the box](../image/screenshot_lb4.png){width=6.3cm height=5.325cm}
The handler corresponds to `btn1` changes its label.
The handler corresponds to `btn2` destroys the top-level window and the application quits.
2020-12-21 13:12:05 +01:00