Gtk4-tutorial/docs/sec5.html
2022-04-24 12:13:40 +09:00

247 lines
18 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="generator" content="pandoc" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
<title>Gtk4 tutorial</title>
<style>
code{white-space: pre-wrap;}
span.smallcaps{font-variant: small-caps;}
span.underline{text-decoration: underline;}
div.column{display: inline-block; vertical-align: top; width: 50%;}
div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
ul.task-list{list-style: none;}
pre{overflow: visible;}
pre > code.sourceCode { white-space: pre; position: relative; }
pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
pre > code.sourceCode > span:empty { height: 1.2em; }
code.sourceCode > span { color: inherit; text-decoration: inherit; }
div.sourceCode { margin: 1em 0; }
pre.sourceCode { margin: 0; }
@media screen {
div.sourceCode { overflow: auto; }
}
@media print {
pre > code.sourceCode { white-space: pre-wrap; }
pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
}
pre.numberSource code
{ counter-reset: source-line 0; }
pre.numberSource code > span
{ position: relative; left: -4em; counter-increment: source-line; }
pre.numberSource code > span > a:first-child::after
{ content: counter(source-line);
position: relative; left: -1em; text-align: right; vertical-align: baseline;
border: none; display: inline-block;
-webkit-touch-callout: none; -webkit-user-select: none;
-khtml-user-select: none; -moz-user-select: none;
-ms-user-select: none; user-select: none;
padding: 0 4px; width: 4em;
color: #aaaaaa;
}
pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa; padding-left: 4px; }
div.sourceCode
{ }
@media screen {
pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
}
code span.al { color: #ff0000; font-weight: bold; } /* Alert */
code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
code span.at { color: #7d9029; } /* Attribute */
code span.bn { color: #40a070; } /* BaseN */
code span.bu { } /* BuiltIn */
code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
code span.ch { color: #4070a0; } /* Char */
code span.cn { color: #880000; } /* Constant */
code span.co { color: #60a0b0; font-style: italic; } /* Comment */
code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
code span.do { color: #ba2121; font-style: italic; } /* Documentation */
code span.dt { color: #902000; } /* DataType */
code span.dv { color: #40a070; } /* DecVal */
code span.er { color: #ff0000; font-weight: bold; } /* Error */
code span.ex { } /* Extension */
code span.fl { color: #40a070; } /* Float */
code span.fu { color: #06287e; } /* Function */
code span.im { } /* Import */
code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
code span.kw { color: #007020; font-weight: bold; } /* Keyword */
code span.op { color: #666666; } /* Operator */
code span.ot { color: #007020; } /* Other */
code span.pp { color: #bc7a00; } /* Preprocessor */
code span.sc { color: #4070a0; } /* SpecialChar */
code span.ss { color: #bb6688; } /* SpecialString */
code span.st { color: #4070a0; } /* String */
code span.va { color: #19177c; } /* Variable */
code span.vs { color: #4070a0; } /* VerbatimString */
code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
div.sourceCode { margin: 10px; padding: 16px 10px 8px 10px; border: 2px solid silver; background-color: ghostwhite; overflow-x:scroll}
pre:not(.sourceCode) { margin: 10px; padding: 16px 10px 8px 10px; border: 2px solid silver; background-color: ghostwhite; overflow-x:scroll}
table {margin-left: auto; margin-right: auto; border-collapse: collapse; border: 1px solid;}
th {padding: 2px 6px; border: 1px solid; background-color: ghostwhite;}
td {padding: 2px 6px; border: 1px solid;}
img {display: block; margin-left: auto; margin-right: auto;}
figcaption {text-align: center;}
</style>
</head>
<body style="padding-top: 70px;">
<div class="container">
<nav class="navbar fixed-top navbar-expand-lg navbar-dark bg-primary">
<div class="container-fluid">
<span class="navbar-brand">Gtk4 tutorial</span>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
<li class="nav-item">
<a class="nav-link" href="index.html">Home</a>
</li>
<li class="nav-item">
<a class="nav-link" href="sec4.html">Prev: section4</a>
</li>
<li class="nav-item">
<a class="nav-link" href="sec6.html">Next: section6</a>
</li>
</ul>
</div>
</div>
</nav>
<h1 id="widgets-2">Widgets (2)</h1>
<h2 id="gtktextview-gtktextbuffer-and-gtkscrolledwindow">GtkTextView, GtkTextbuffer and GtkScrolledWindow</h2>
<h3 id="gtktextview-and-gtktextbuffer">GtkTextView and GtkTextBuffer</h3>
<p>GtkTextview is a widget for multi-line text editing. GtkTextBuffer is a text buffer which is connected to GtkTextView. See the sample program <code>tfv1.c</code> below.</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode numberSource C numberLines"><code class="sourceCode c"><span id="cb1-1"><a href="#cb1-1"></a><span class="pp">#include </span><span class="im">&lt;gtk/gtk.h&gt;</span></span>
<span id="cb1-2"><a href="#cb1-2"></a></span>
<span id="cb1-3"><a href="#cb1-3"></a><span class="dt">static</span> <span class="dt">void</span></span>
<span id="cb1-4"><a href="#cb1-4"></a>app_activate (GApplication *app, gpointer user_data) {</span>
<span id="cb1-5"><a href="#cb1-5"></a> GtkWidget *win;</span>
<span id="cb1-6"><a href="#cb1-6"></a> GtkWidget *tv;</span>
<span id="cb1-7"><a href="#cb1-7"></a> GtkTextBuffer *tb;</span>
<span id="cb1-8"><a href="#cb1-8"></a> gchar *text;</span>
<span id="cb1-9"><a href="#cb1-9"></a></span>
<span id="cb1-10"><a href="#cb1-10"></a> text =</span>
<span id="cb1-11"><a href="#cb1-11"></a> <span class="st">&quot;Once upon a time, there was an old man who was called Taketori-no-Okina. &quot;</span></span>
<span id="cb1-12"><a href="#cb1-12"></a> <span class="st">&quot;It is a japanese word that means a man whose work is making bamboo baskets.</span><span class="sc">\n</span><span class="st">&quot;</span></span>
<span id="cb1-13"><a href="#cb1-13"></a> <span class="st">&quot;One day, he went into a mountain and found a shining bamboo. &quot;</span></span>
<span id="cb1-14"><a href="#cb1-14"></a> <span class="st">&quot;</span><span class="sc">\&quot;</span><span class="st">What a mysterious bamboo it is!,</span><span class="sc">\&quot;</span><span class="st"> he said. &quot;</span></span>
<span id="cb1-15"><a href="#cb1-15"></a> <span class="st">&quot;He cut it, then there was a small cute baby girl in it. &quot;</span></span>
<span id="cb1-16"><a href="#cb1-16"></a> <span class="st">&quot;The girl was shining faintly. &quot;</span></span>
<span id="cb1-17"><a href="#cb1-17"></a> <span class="st">&quot;He thought this baby girl is a gift from Heaven and took her home.</span><span class="sc">\n</span><span class="st">&quot;</span></span>
<span id="cb1-18"><a href="#cb1-18"></a> <span class="st">&quot;His wife was surprized at his tale. &quot;</span></span>
<span id="cb1-19"><a href="#cb1-19"></a> <span class="st">&quot;They were very happy because they had no children. &quot;</span></span>
<span id="cb1-20"><a href="#cb1-20"></a> ;</span>
<span id="cb1-21"><a href="#cb1-21"></a> win = gtk_application_window_new (GTK_APPLICATION (app));</span>
<span id="cb1-22"><a href="#cb1-22"></a> gtk_window_set_title (GTK_WINDOW (win), <span class="st">&quot;Taketori&quot;</span>);</span>
<span id="cb1-23"><a href="#cb1-23"></a> gtk_window_set_default_size (GTK_WINDOW (win), <span class="dv">400</span>, <span class="dv">300</span>);</span>
<span id="cb1-24"><a href="#cb1-24"></a></span>
<span id="cb1-25"><a href="#cb1-25"></a> tv = gtk_text_view_new ();</span>
<span id="cb1-26"><a href="#cb1-26"></a> tb = gtk_text_view_get_buffer (GTK_TEXT_VIEW (tv));</span>
<span id="cb1-27"><a href="#cb1-27"></a> gtk_text_buffer_set_text (tb, text, -<span class="dv">1</span>);</span>
<span id="cb1-28"><a href="#cb1-28"></a> gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (tv), GTK_WRAP_WORD_CHAR);</span>
<span id="cb1-29"><a href="#cb1-29"></a></span>
<span id="cb1-30"><a href="#cb1-30"></a> gtk_window_set_child (GTK_WINDOW (win), tv);</span>
<span id="cb1-31"><a href="#cb1-31"></a></span>
<span id="cb1-32"><a href="#cb1-32"></a> gtk_widget_show (win);</span>
<span id="cb1-33"><a href="#cb1-33"></a>}</span>
<span id="cb1-34"><a href="#cb1-34"></a></span>
<span id="cb1-35"><a href="#cb1-35"></a><span class="dt">int</span></span>
<span id="cb1-36"><a href="#cb1-36"></a>main (<span class="dt">int</span> argc, <span class="dt">char</span> **argv) {</span>
<span id="cb1-37"><a href="#cb1-37"></a> GtkApplication *app;</span>
<span id="cb1-38"><a href="#cb1-38"></a> <span class="dt">int</span> stat;</span>
<span id="cb1-39"><a href="#cb1-39"></a></span>
<span id="cb1-40"><a href="#cb1-40"></a> app = gtk_application_new (<span class="st">&quot;com.github.ToshioCP.tfv1&quot;</span>, G_APPLICATION_FLAGS_NONE);</span>
<span id="cb1-41"><a href="#cb1-41"></a> g_signal_connect (app, <span class="st">&quot;activate&quot;</span>, G_CALLBACK (app_activate), NULL);</span>
<span id="cb1-42"><a href="#cb1-42"></a> stat = g_application_run (G_APPLICATION (app), argc, argv);</span>
<span id="cb1-43"><a href="#cb1-43"></a> g_object_unref (app);</span>
<span id="cb1-44"><a href="#cb1-44"></a> <span class="cf">return</span> stat;</span>
<span id="cb1-45"><a href="#cb1-45"></a>}</span></code></pre></div>
<p>Look at line 25. A GtkTextView instance is created and its pointer is assigned to <code>tv</code>. When the GtkTextView instance is created, a GtkTextBuffer instance is also created and connected to the GtkTextView automatically. “GtkTextBuffer instance” will be referred to simply as “GtkTextBuffer” or “buffer”. In the next line, the pointer to the buffer is got and assigned to <code>tb</code>. Then, the text from line 10 to 20 is assigned to the buffer.</p>
<p>GtkTextView has a wrap mode. When it is set to <code>GTK_WRAP_WORD_CHAR</code>, text wraps in between words, or if that is not enough, also between graphemes.</p>
<p>In line 30, <code>tv</code> is added to <code>win</code> as a child.</p>
<p>Now compile and run it.</p>
<figure>
<img src="image/screenshot_tfv1.png" alt="" /><figcaption>GtkTextView</figcaption>
</figure>
<p>Theres an I-beam pointer in the window. You can add or delete any characters on the GtkTextview, and your changes are kept in the GtkTextBuffer. If you add more characters beyond the limit of the window, the height increases and the window extends. If the height gets bigger than the height of the display screen, you wont be able to control the size of the window, and change it back to the original size. This is a problem and shows that there is a bug in our program. This can solve it by adding a GtkScrolledWindow between the GtkApplicationWindow and GtkTextView.</p>
<h3 id="gtkscrolledwindow">GtkScrolledWindow</h3>
<p>What we need to do is:</p>
<ul>
<li>Create a GtkScrolledWindow and insert it as a child of the GtkApplicationWindow; and</li>
<li>Insert the GtkTextView widget to the GtkScrolledWindow as a child.</li>
</ul>
<p>Modify <code>tfv1.c</code> and save it as <code>tfv2.c</code>. The difference between these two files is small.</p>
<pre><code>$ cd tfv; diff tfv1.c tfv2.c
5a6
&gt; GtkWidget *scr;
24a26,28
&gt; scr = gtk_scrolled_window_new ();
&gt; gtk_window_set_child (GTK_WINDOW (win), scr);
&gt;
30c34
&lt; gtk_window_set_child (GTK_WINDOW (win), tv);
---
&gt; gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (scr), tv);
40c44
&lt; app = gtk_application_new (&quot;com.github.ToshioCP.tfv1&quot;, G_APPLICATION_FLAGS_NONE);
---
&gt; app = gtk_application_new (&quot;com.github.ToshioCP.tfv2&quot;, G_APPLICATION_FLAGS_NONE);</code></pre>
<p>Here is the complete code of <code>tfv2.c</code>.</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode numberSource C numberLines"><code class="sourceCode c"><span id="cb3-1"><a href="#cb3-1"></a><span class="pp">#include </span><span class="im">&lt;gtk/gtk.h&gt;</span></span>
<span id="cb3-2"><a href="#cb3-2"></a></span>
<span id="cb3-3"><a href="#cb3-3"></a><span class="dt">static</span> <span class="dt">void</span></span>
<span id="cb3-4"><a href="#cb3-4"></a>app_activate (GApplication *app, gpointer user_data) {</span>
<span id="cb3-5"><a href="#cb3-5"></a> GtkWidget *win;</span>
<span id="cb3-6"><a href="#cb3-6"></a> GtkWidget *scr;</span>
<span id="cb3-7"><a href="#cb3-7"></a> GtkWidget *tv;</span>
<span id="cb3-8"><a href="#cb3-8"></a> GtkTextBuffer *tb;</span>
<span id="cb3-9"><a href="#cb3-9"></a> gchar *text;</span>
<span id="cb3-10"><a href="#cb3-10"></a></span>
<span id="cb3-11"><a href="#cb3-11"></a> text =</span>
<span id="cb3-12"><a href="#cb3-12"></a> <span class="st">&quot;Once upon a time, there was an old man who was called Taketori-no-Okina. &quot;</span></span>
<span id="cb3-13"><a href="#cb3-13"></a> <span class="st">&quot;It is a japanese word that means a man whose work is making bamboo baskets.</span><span class="sc">\n</span><span class="st">&quot;</span></span>
<span id="cb3-14"><a href="#cb3-14"></a> <span class="st">&quot;One day, he went into a mountain and found a shining bamboo. &quot;</span></span>
<span id="cb3-15"><a href="#cb3-15"></a> <span class="st">&quot;</span><span class="sc">\&quot;</span><span class="st">What a mysterious bamboo it is!,</span><span class="sc">\&quot;</span><span class="st"> he said. &quot;</span></span>
<span id="cb3-16"><a href="#cb3-16"></a> <span class="st">&quot;He cut it, then there was a small cute baby girl in it. &quot;</span></span>
<span id="cb3-17"><a href="#cb3-17"></a> <span class="st">&quot;The girl was shining faintly. &quot;</span></span>
<span id="cb3-18"><a href="#cb3-18"></a> <span class="st">&quot;He thought this baby girl is a gift from Heaven and took her home.</span><span class="sc">\n</span><span class="st">&quot;</span></span>
<span id="cb3-19"><a href="#cb3-19"></a> <span class="st">&quot;His wife was surprized at his tale. &quot;</span></span>
<span id="cb3-20"><a href="#cb3-20"></a> <span class="st">&quot;They were very happy because they had no children. &quot;</span></span>
<span id="cb3-21"><a href="#cb3-21"></a> ;</span>
<span id="cb3-22"><a href="#cb3-22"></a> win = gtk_application_window_new (GTK_APPLICATION (app));</span>
<span id="cb3-23"><a href="#cb3-23"></a> gtk_window_set_title (GTK_WINDOW (win), <span class="st">&quot;Taketori&quot;</span>);</span>
<span id="cb3-24"><a href="#cb3-24"></a> gtk_window_set_default_size (GTK_WINDOW (win), <span class="dv">400</span>, <span class="dv">300</span>);</span>
<span id="cb3-25"><a href="#cb3-25"></a></span>
<span id="cb3-26"><a href="#cb3-26"></a> scr = gtk_scrolled_window_new ();</span>
<span id="cb3-27"><a href="#cb3-27"></a> gtk_window_set_child (GTK_WINDOW (win), scr);</span>
<span id="cb3-28"><a href="#cb3-28"></a></span>
<span id="cb3-29"><a href="#cb3-29"></a> tv = gtk_text_view_new ();</span>
<span id="cb3-30"><a href="#cb3-30"></a> tb = gtk_text_view_get_buffer (GTK_TEXT_VIEW (tv));</span>
<span id="cb3-31"><a href="#cb3-31"></a> gtk_text_buffer_set_text (tb, text, -<span class="dv">1</span>);</span>
<span id="cb3-32"><a href="#cb3-32"></a> gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (tv), GTK_WRAP_WORD_CHAR);</span>
<span id="cb3-33"><a href="#cb3-33"></a></span>
<span id="cb3-34"><a href="#cb3-34"></a> gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (scr), tv);</span>
<span id="cb3-35"><a href="#cb3-35"></a></span>
<span id="cb3-36"><a href="#cb3-36"></a> gtk_widget_show (win);</span>
<span id="cb3-37"><a href="#cb3-37"></a>}</span>
<span id="cb3-38"><a href="#cb3-38"></a></span>
<span id="cb3-39"><a href="#cb3-39"></a><span class="dt">int</span></span>
<span id="cb3-40"><a href="#cb3-40"></a>main (<span class="dt">int</span> argc, <span class="dt">char</span> **argv) {</span>
<span id="cb3-41"><a href="#cb3-41"></a> GtkApplication *app;</span>
<span id="cb3-42"><a href="#cb3-42"></a> <span class="dt">int</span> stat;</span>
<span id="cb3-43"><a href="#cb3-43"></a></span>
<span id="cb3-44"><a href="#cb3-44"></a> app = gtk_application_new (<span class="st">&quot;com.github.ToshioCP.tfv2&quot;</span>, G_APPLICATION_FLAGS_NONE);</span>
<span id="cb3-45"><a href="#cb3-45"></a> g_signal_connect (app, <span class="st">&quot;activate&quot;</span>, G_CALLBACK (app_activate), NULL);</span>
<span id="cb3-46"><a href="#cb3-46"></a> stat = g_application_run (G_APPLICATION (app), argc, argv);</span>
<span id="cb3-47"><a href="#cb3-47"></a> g_object_unref (app);</span>
<span id="cb3-48"><a href="#cb3-48"></a> <span class="cf">return</span> stat;</span>
<span id="cb3-49"><a href="#cb3-49"></a>}</span></code></pre></div>
<p>Compile and run it. Notice how this time the window doesnt extend when you type a lot of characters, it just scrolls and displays a slider.</p>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>
</body>
</html>