File: 03_getting_the_signal.js.page

package info (click to toggle)
gnome-devel-docs 40.3-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 79,188 kB
  • sloc: javascript: 2,514; xml: 2,407; ansic: 2,229; python: 1,854; makefile: 805; sh: 499; cpp: 131
file content (764 lines) | stat: -rw-r--r-- 31,651 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
<?xml version="1.0" encoding="utf-8"?>
<page xmlns="http://projectmallard.org/1.0/" xmlns:its="http://www.w3.org/2005/11/its" xmlns:xi="http://www.w3.org/2001/XInclude" type="topic" style="task" id="03_getting_the_signal.js" xml:lang="sv">
  <info>
    <link type="guide" xref="beginner.js#tutorials"/>
    <link type="seealso" xref="button.js"/>
    <link type="seealso" xref="entry.js"/>
    <link type="seealso" xref="radiobutton.js"/>
    <link type="seealso" xref="switch.js"/>
    <revision version="0.1" date="2012-08-12" status="draft"/>

    <credit type="author copyright">
      <name>Taryn Fox</name>
      <email its:translate="no">jewelfox@fursona.net</email>
      <years>2012</years>
    </credit>

    <desc>Skapa knappar och andra komponenter som gör saker när du klickar på dem.</desc>
  
    <mal:credit xmlns:mal="http://projectmallard.org/1.0/" type="translator copyright">
      <mal:name>Sebastian Rasmussen</mal:name>
      <mal:email>sebras@gmail.com</mal:email>
      <mal:years>2019</mal:years>
    </mal:credit>
  
    <mal:credit xmlns:mal="http://projectmallard.org/1.0/" type="translator copyright">
      <mal:name>Anders Jonsson</mal:name>
      <mal:email>anders.jonsson@norsjovallen.se</mal:email>
      <mal:years>2021</mal:years>
    </mal:credit>
  </info>

  <title>3. Få signalen</title>
  <synopsis>
    <p>I den senaste handledningen lärde vi oss hur man skapar komponenter så som Label, Image och Button. Här kommer vi att lära oss att få Button och andra inmatningskomponenter att faktiskt göra saker, genom att skriva funktioner som hanterar signalerna de skickar när de klickas på eller interageras med.</p>
  </synopsis>

  <links type="section"/>

  <section id="application">
    <title>Ett grundläggande program</title>
    <p>I GNOME skickar komponenter som du kan interagera med, så som Button och Switch, ut signaler när de klickas på eller aktiveras. En Button till exempel skickar ut signalen ”clicked” när någon klickar på den. När detta inträffar letar GNOME efter delen i din kod som säger vad som ska hända.</p>
    <p>Hur skriver vi den koden? Genom att ansluta Buttons ”clicked”-signal till en återanropsfunktion, vilket är en funktion du skriver enkom för att hantera den signalen. Så närhelst den signalen skickas ut kommer funktionen som är ansluten till den signalen att köra.</p>
    <p>Här är ett extremt enkelt exempel:</p>

    <media type="image" mime="image/png" src="media/03_jssignal_01.png"/>

    <p>Detta ApplicationWindow har en Button och en Label inuti, arrangerade via en Grid. Närhelst Button blir klickad på ökar en variabel som innehåller antalet kakor med ett och Labeln som visar hur många kakor det finns uppdateras.</p>
    <note style="tip"><p>Kakorna i detta exempel är inte samma som kakorna som du kan få från webbplatser, vilka lagrar din inloggningsinformation och håller reda på vilka webbplatser du besökt. De är bara fiktiva belöningar. Du kan baka några riktiga om du vill.</p></note>
    <p>Här är den grundläggande standardkoden som kör vid programmets start, innan vi börjar skapa fönstret och komponenter. Förutom att programmet har ett unikt namn är den största förändringen från standardkoden att vi skapar en global variabel precis i början för att lagra antalet kakor.</p>
    <code mime="application/javascript">
#!/usr/bin/gjs

imports.gi.versions.Gtk = '3.0';
const Gtk = imports.gi.Gtk;

// Vi börjar med 0 kakor
var cookies = 0;

class GettingTheSignal {
    // Skapa programmet i sig
    constructor() {
        this.application = new Gtk.Application();

        // Anslut ”active”- och ”startup”-signaler till återanropsfunktionerna
        this.application.connect('activate', this._onActivate.bind(this));
        this.application.connect('startup', this._onStartup.bind(this));
    }

    // Återanropsfunktion för ”activate”-signal, visar fönstret när den aktiveras
    _onActivate() {
        this._window.present();
    }

    // Återanropsfunktionen för ”startup”-signalen bygger användargränssnittet
    _onStartup() {
        this._buildUI ();
    }
</code>
    <p>Titta på delen som använder vårt programs anslutningsmetod och bindning för att ansluta dess ”activate”- och ”startup”-signaler till funktionerna som visar fönstret och bygger användargränssnittet. Vi kommer att göra samma sak med vår Button när vi kommer till det, förutom att vi kommer att ansluta dess ”clicked”-signal istället.</p>
  </section>

  <section id="button">
    <title>Klicka på knappen</title>

    <p>Som vanligt kommer vi att placera all kod för att skapa vår Button och andra komponenter inuti funktionen _buildUI, vilken anropas när programmet startar.</p>
    <code mime="application/javascript">
    // Bygg programmets användargränssnitt
    _buildUI() {
</code>

    <p>Först skapar vi fönstret i sig:</p>
    <code mime="application/javascript">
        // Skapa programfönstret
        this._window = new Gtk.ApplicationWindow({
            application: this.application,
            window_position: Gtk.WindowPosition.CENTER,
            default_height: 200,
            default_width: 400,
            title: "Klicka på knappen för att få en kaka!"});
</code>
    <p>Notera att vi har satt egenskaperna default_height och default_width. Dessa låter oss styra hur högt och brett, i bildpunkter, som ApplicationWindow kommer att vara.</p>
    <p>Härnäst kommer vi att skapa Labeln som visar oss antalet kakor. Vi kan använda kakvariabeln som en del av Labelns label-egenskap.</p>
    <code mime="application/javascript">
        // Skapa etiketten
        this._cookieLabel = new Gtk.Label ({
            label: "Antal kakor: " + cookies });
</code>

    <p>Nu skapar vi vår Button. Vi sätter dess label-egenskap så den visar texten som vi vill ha på vår Button, och vi ansluter dess ”clicked”-signal till en funktion kallad _getACookie, vilken vi kommer att skriva efter att vi är klara med att bygga vårt programs användargränssnitt.</p>
    <code mime="application/javascript">
        // Skapa kakknappen
        this._cookieButton = new Gtk.Button ({ label: "Få en kaka" });

        // Anslut kakknappen till funktionen som hanterar när den blir klickad på
        this._cookieButton.connect ('clicked', this._getACookie.bind(this));
</code>
    <p>Avslutningsvis skapar vi en Grid, fäster vår Label och Button till den och lägger till den till fönstret och ber fönstret att visa sig själv och sitt innehåll. Det är allt vi behöver göra inuti _buildUI-funktionen, så vi stänger den med en klammerparentes så väl som ett kommatecken som berättar för GNOME att fortsätta med nästa funktion. Notera att även om vi skrev koden för Label först kan vi fortfarande fästa den till Grid på ett sätt som placerar den längst ned.</p>
    <code mime="application/javascript">
        // Skapa ett rutnät för att ordna allting inuti
        this._grid = new Gtk.Grid ({
            halign: Gtk.Align.CENTER,
            valign: Gtk.Align.CENTER,
            row_spacing: 20 });

        // Placera allting inuti rutnätet
        this._grid.attach (this._cookieButton, 0, 0, 1, 1);
        this._grid.attach (this._cookieLabel, 0, 1, 1, 1);

        // Lägg till rutnätet till fönstret
        this._window.add (this._grid);

        // Visa fönstret och alla dess barnkomponenter
        this._window.show_all();

    }
</code>
    <p>Nu kommer vi att skriva _getACookie-funktionen. När vår Button skickar ut sin ”clicked”-signal kommer koden i denna funktion att köras. I detta fall är allt den ska göra att öka antalet kakor med 1 och uppdatera vår Label till att visa det nya antalet kakor. Vi gör detta via Labelns set_label-metod.</p>
    <note style="tip"><p>Många komponenter har samma egenskaper och metoder. Både Label och Button har till exempel en label-egenskap som säger vilken text som finns inuti dem, och get_label- och set_label-metoder som låter dig se vad texten är, respektive ändra den. Så om du lär dig hur en komponent fungerar kommer du också att veta hur andra liknande komponenter fungerar.</p></note>
    <code mime="application/javascript">
    _getACookie: function() {

        // Öka antalet kakor med 1 och uppdatera etiketten
        cookies++;
        this._cookieLabel.set_label ("Antal kakor: " + cookies);

    }

};
</code>

    <p>Avslutningsvis kör vi programmet med samma kod som i vår senaste handledning.</p>
    <code mime="application/javascript">
// Kör programmet
let app = new GettingTheSignal ();
app.application.run (ARGV);
</code>
  </section>

  <section id="switch">
    <title>Slå om brytaren</title>
    <p>Knappar är inte den enda typen av komponenter i GTK+-verktygslådan. Vi kan också använda brytare (Switch) som den i detta exempel. En Switch har inte en etikettegenskap, så vi måste skapa en separat Label intill som berättar vad den gör.</p>

    <media type="image" mime="image/png" src="media/03_jssignal_02.png"/>

    <p>En Switch har två positioner, av och på. När en Switch är påslagen kommer dess text och bakgrundsfärg att ändras, så du kan se vilken position den är i.</p>

    <p>Du kan ha sett Switchar som dessa i GNOME:s hjälpmedelsmeny, vilken låter dig slå på och av funktioner så som stor text och skärmtangentbord. I detta fall styr Switchen vår fiktiva kakautomat. Om Switchen är påslagen kan du få kakor genom att klicka på knappen ”Få en kaka”. Om den är avslagen, kommer klickande på knappen inte att göra något.</p>
    <note style="tip"><p>Du kan nå hjälpmedelsmenyn genom att klicka på konturen av en människa nära ditt namn i övre högra hörnet av skärmen.</p></note>
    <p>Så här skapar vi Switchen:</p>
    <code mime="application/javascript">
        // Skapa brytaren som styr huruvida du kan vinna eller ej
        this._cookieSwitch = new Gtk.Switch ();
</code>

    <p>Vi behöver faktiskt inte ansluta Switchen till någonting. Allt vi behöver göra är att skriva en if-sats i vår _getACookie-funktion, för att se om Switchen är påslagen. Om vi skulle vilja att något ska hända direkt när Switchen slås om, måste vi ansluta till dess notify::active-signal, så här:</p>
    <code mime="application/javascript">
        // Anslut brytaren till funktionen som hanterar den
        this._cookieSwitch.connect ('notify::active', this._cookieDispenser.bind(this));
</code>

    <p>En Switch är som standard satt till avslagen. Om vi vill att Switchen ska börja påslagen, måste vi sätta värdet för dess active-egenskap till true när vi skapar den.</p>
    <code mime="application/javascript">
        this._cookieSwitch = new Gtk.Switch ({ active: true });
</code>

    <p>Låt oss dock börja med att skapa den normalt, och sedan skapa en medföljande Label. Vi vill att Switchen och Labeln ska vara alldeles intill varandra, så vi skapar en Grid bara för dem, sedan stoppar vi denna Grid inuti vår större Grid som innehåller alla komponenterna. Här är hur koden skall se ut för allt detta:</p>
    <code mime="application/javascript">
        // Skapa brytaren som styr huruvida du kan vinna eller ej
        this._cookieSwitch = new Gtk.Switch ();

        // Skapa etiketten som medföljer brytaren
        this._switchLabel = new Gtk.Label ({
            label: "Kakautomat" });

        // Skapa ett rutnät för brytaren och dess etikett
        this._switchGrid = new Gtk.Grid ({
            halign: Gtk.Align.CENTER,
            valign: Gtk.Align.CENTER });

        // Stoppa brytaren och dess etikett inuti det rutnätet
        this._switchGrid.attach (this._switchLabel, 0, 0, 1, 1);
        this._switchGrid.attach (this._cookieSwitch, 1, 0, 1, 1);
</code>

    <p>Och nu arrangerar vi allting inuti vår större Grid på följande sätt.</p>
    <code mime="application/javascript">
        // Stoppa allting inuti rutnätet
        this._grid.attach (this._cookieButton, 0, 0, 1, 1);
        this._grid.attach (this._switchGrid, 0, 1, 1, 1);
        this._grid.attach (this._cookieLabel, 0, 2, 1, 1);
</code>

    <p>Nu ändrar vi _getACookie-funktionen så att den kontrollerar om kakautomaten är påslagen. Vi gör det genom att använda Switchens get_active-metod. Den returnerar true om Switchen är påslagen, och false om Switchen är avslagen.</p>
    <note style="tip"><p>När en metod används inuti en if-sats så här, kommer koden inuti if-satsen att köras om metoden returnerar true.</p></note>
    <code mime="application/javascript">
    _getACookie() {

        // Är kakautomaten påslagen?
        if (this._cookieSwitch.get_active()) {

            // Öka antalet kakor med 1 och uppdatera etiketten
            cookies++;
            this._cookieLabel.set_label ("Antal kakor: " + cookies);

        }

    }
</code>

  </section>

  <section id="radio">
    <title>Ratta på radion</title>

    <p>En annan sorts inmatningskomponent som vi kan använda kallas för RadioButton. Du skapar dem i grupper, och då kan endast en RadioButton i en grupp vara vald samtidigt. De kallas radioknappar för att de fungerar som knapparna för förinställda kanaler i en gammaldags bilradio. Radion kunde bara vara inställd på en kanal åt gången, så närhelst du tryckte på en knapp så fick det en annan att poppa ut igen.</p>

    <media type="image" mime="image/png" src="media/03_jssignal_03.png"/>

    <p>Låt oss först ändra namnet på vårt ApplicationWindow och öka dess border_width-egenskap, så att våra komponenter inte är så tätt packade. Värdet border_width är antalet bildpunkter mellan alla komponenter och fönstrets kant.</p>
    <code mime="application/javascript">
        // Skapa programfönstret
        this._window = new Gtk.ApplicationWindow({
            application: this.application,
            window_position: Gtk.WindowPosition.CENTER,
            default_height: 200,
            default_width: 400,
            border_width: 20,
            title: "Välj den som säger ”kaka”!"});
</code>

    <p>Efter det skapar vi RadioButton-knapparna. Kommer du ihåg att de skapas i grupper? Vi gör det genom att ställa in group-egenskapen för varje ny RadioButton till namnet på en annan RadioButton.</p>
    <code mime="application/javascript">
        // Create the radio buttons
        this._cookieRadio = new Gtk.RadioButton ({ label: "Kaka" });
        this._notCookieOne = new Gtk.RadioButton ({ label: "Inte kaka",
            group: this._cookieRadio });
        this._notCookieTwo = new Gtk.RadioButton ({ label: "Inte kaka",
            group: this._cookieRadio });
</code>

    <p>Härnäst skapar vi en Grid för RadioButton-knapparna. Kom ihåg att vi inte behöver arrangera saker i en Grid i samma ordning som vi skapar dem.</p>
    <code mime="application/javascript">
        // Arrangera radioknapparna i sitt eget rutnät
        this._radioGrid = new Gtk.Grid ();
        this._radioGrid.attach (this._notCookieOne, 0, 0, 1, 1);
        this._radioGrid.attach (this._cookieRadio, 0, 1, 1, 1);
        this._radioGrid.attach (this._notCookieTwo, 0, 2, 1, 1);
</code>

    <p>Vanligen är det den RadioButton som är vald som standard som används som namnet på gruppen. Vi vill dock att den första ”Inte kaka”-knappen ska vara vald som standard, så vi använder dess set_active-metod.</p>
    <note style="tip"><p>Vi skulle också kunna ställa in dess active-egenskap till true när vi skapar den.</p></note>
    <code mime="application/javascript">
        // Ställ in knappen högst upp att vara aktiv som standard
        this._notCookieOne.set_active (true);
</code>

    <p>Nu arrangerar vi allting i vår huvud-Grid som vanligt …</p>
    <code mime="application/javascript">
        // Stoppa allting inuti rutnätet
        this._grid.attach (this._radioGrid, 0, 0, 1, 1);
        this._grid.attach (this._cookieButton, 0, 1, 1, 1);
        this._grid.attach (this._cookieLabel, 0, 2, 1, 1);

</code>

    <p>Sedan ändrar vi vår _getACookie-funktion så att den testar om kakknappen är den som har valts.</p>
    <code mime="application/javascript">
    _getACookie() {

        // Valde du ”kaka” istället för ”inte kaka”?
        if (this._cookieRadio.get_active()) {

            // Öka antalet kakor med 1 och uppdatera etiketten
            cookies++;
            this._cookieLabel.set_label ("Antal kakor: " + cookies);

        }

    }
</code>

  </section>

  <section id="spell">
    <title>Kan du stava till ”kaka”?</title>

    <p>Den sista inmatningskomponenten som vi kommer att tala om är komponenten Entry, vilken används för textinmatningsfält med en ensam rad.</p>
    <note style="tip"><p>Om du behöver kunna mata in ett helt stycke eller mer, exempelvis om du bygger en textredigerare, så kommer du vilja ta en titt på den mycket mer anpassningsbara <link xref="textview.js">TextView</link>-komponenten.</p></note>
    <media type="image" mime="image/png" src="media/03_jssignal_04.png"/>

    <p>Efter att vi ändrar fönstrets namn skapar vi Entry-komponenten.</p>
    <code mime="application/javascript">
        // Skapa textinmatningsfältet
        this._spellCookie = new Gtk.Entry ();
</code>

    <p>Sedan arrangerar vi allt i vår Grid …</p>
    <code mime="application/javascript">
        // Stoppa allting inuti rutnätet
        this._grid.attach (this._spellCookie, 0, 0, 1, 1);
        this._grid.attach (this._cookieButton, 0, 1, 1, 1);
        this._grid.attach (this._cookieLabel, 0, 2, 1, 1);
</code>

    <p>Nu ändrar vi if-satsen för _getACookie igen, och använder get_text-metoden för Entryt för att få texten som du matade in i det och se om du stavade ”kaka” rätt. Vi bryr oss inte om du använder små eller stora bokstäver i ”kaka”, så vi använder Javascripts inbyggda toLowerCase-metod för att ändra texten för Entryt till gemener inuti if-satsen.</p>
    <note style="tip"><p>En Entry-komponent har ingen label-egenskap, vilket är en inställd textsträng som användaren inte kan ändra. (Du kan exempelvis vanligen inte ändra etiketten på en Button.) Istället har den en text-egenskap, vilken ändras så att den motsvarar vad användaren skriver in.</p></note>
    <code mime="application/javascript">
    _getACookie() {

        // Stavade du ”kaka” rätt?
        if ((this._spellCookie.get_text()).toLowerCase() == "kaka") {

            // Öka antalet kakor med 1 och uppdatera etiketten
            cookies++;
            this._cookieLabel.set_label ("Antal kakor: " + cookies);

        }

    }
</code>

  </section>

  <section id="whats_next">
    <title>Vad är nästa steg?</title>
    <p>Fortsätt läsa om du vill se den fullständiga koden för varje version av vårt kakmakarprogram.</p>
    <note style="tip"><p>Huvudsidan för Javascripthandledningar har <link xref="beginner.js#buttons">mer detaljerade kodexempel</link> för varje inmatningskomponent, däribland flera som inte täcks här.</p></note>

  </section>

  <section id="complete">
    <title>Fullständiga kodexempel</title>

    <links type="section"/>

    <section id="buttonsample">
      <title>Kodexempel med Button</title>
      <media type="image" mime="image/png" src="media/03_jssignal_01.png"/>
      <code mime="application/javascript" style="numbered">#!/usr/bin/gjs

imports.gi.versions.Gtk = '3.0';
const Gtk = imports.gi.Gtk;

// Vi börjar med 0 kakor
var cookies = 0;

class GettingTheSignal {

    // Skapa programmet i sig
    constructor() {
        this.application = new Gtk.Application();

        // Anslut ”activate”- och ”startup”-signaler till återanropsfunktionerna
        this.application.connect('activate', this._onActivate.bind(this));
        this.application.connect('startup', this._onStartup.bind(this));
    }

    // Återanropsfunktion för ”activate”-signal, visar fönstret när den aktiveras
    _onActivate() {
        this._window.present();
    }

    // Återanropsfunktion för ”startup”-signal bygger användargränssnittet
    _onStartup() {
        this._buildUI();
    }

    // Bytt programmets användargränssnitt
    _buildUI() {

        // Skapa programfönstret
        this._window = new Gtk.ApplicationWindow({
            application: this.application,
            window_position: Gtk.WindowPosition.CENTER,
            default_height: 200,
            default_width: 400,
            title: "Klicka på knappen för att få en kaka!"});

        // Skapa en etikett
        this._cookieLabel = new Gtk.Label ({
            label: "Antal kakor: " + cookies });

        // Skapa kak-knappen
        this._cookieButton = new Gtk.Button ({ label: "Få en kaka" });

        // Anslut kakknappen till funktionen som hanterar klickande på den
        this._cookieButton.connect ('clicked', this._getACookie.bind(this));

        // Skapa ett rutnät för att arrangera allting i
        this._grid = new Gtk.Grid ({
            halign: Gtk.Align.CENTER,
            valign: Gtk.Align.CENTER,
            row_spacing: 20 });

        // Stoppa allting inuti rutnätet
        this._grid.attach (this._cookieButton, 0, 0, 1, 1);
        this._grid.attach (this._cookieLabel, 0, 1, 1, 1);

        // Lägg till rutnätet till fönstret
        this._window.add (this._grid);

        // Visa fönstret och alla barnkomponenter
        this._window.show_all();

    }

    _getACookie() {

        // Öka antalet kakor med 1 och uppdatera etiketten
        cookies++;
        this._cookieLabel.set_label ("Antal kakor: " + cookies);

    }

};

// Kör programmet
let app = new GettingTheSignal ();
app.application.run (ARGV);
</code>
    </section>

    <section id="switchsample">
      <title>Kodexempel med Switch</title>
      <media type="image" mime="image/png" src="media/03_jssignal_02.png"/>
      <code mime="application/javascript" style="numbered">#!/usr/bin/gjs

imports.gi.versions.Gtk = '3.0';
const Gtk = imports.gi.Gtk;

// Vi börjar med 0 kakor
var cookies = 0;

class GettingTheSignal {

    // Skapa programmet i sig
    constructor() {
        this.application = new Gtk.Application();

        // Anslut ”activate”- och ”startup”-signaler till återanropsfunktionerna
        this.application.connect('activate', this._onActivate.bind(this));
        this.application.connect('startup', this._onStartup.bind(this));
    }

    // Återanropsfunktion för ”activate”-signal, visar fönstret när den aktiveras
    _onActivate() {
        this._window.present();
    }

    // Återanropsfunktion för ”startup”-signal bygger användargränssnittet
    _onStartup() {
        this._buildUI();
    }

    // Bygg programmets användargränssnitt
    _buildUI() {

        // Skapa programfönstret
        this._window = new Gtk.ApplicationWindow({
            application: this.application,
            window_position: Gtk.WindowPosition.CENTER,
            default_height: 200,
            default_width: 400,
            title: "Klicka på knappen för att få en kaka!"});

        // Skapa etiketten
        this._cookieLabel = new Gtk.Label ({
            label: "Antal kakor: " + cookies });

        // Skapa kak-knappen
        this._cookieButton = new Gtk.Button ({
            label: "Få en kaka" });

        // Anslut kakknappen till funktionen som hanterar klickande på den
        this._cookieButton.connect ('clicked', this._getACookie.bind(this));

        // Skapa en brytare som styr huruvida du kan vinna eller ej
        this._cookieSwitch = new Gtk.Switch ();

        // Skapa etiketten som följer med brytaren
        this._switchLabel = new Gtk.Label ({
            label: "Kakautomat" });

        // Skapa ett rutnät för brytaren och dess etikett
        this._switchGrid = new Gtk.Grid ({
            halign: Gtk.Align.CENTER,
            valign: Gtk.Align.CENTER });

        // Stoppa brytaren och dess etikett inuti det rutnätet
        this._switchGrid.attach (this._switchLabel, 0, 0, 1, 1);
        this._switchGrid.attach (this._cookieSwitch, 1, 0, 1, 1);

        // Skapa ett rutnät för att arrangera allting annat inuti
        this._grid = new Gtk.Grid ({
            halign: Gtk.Align.CENTER,
            valign: Gtk.Align.CENTER,
            row_spacing: 20 });

        // Stoppa allting inuti rutnätet
        this._grid.attach (this._cookieButton, 0, 0, 1, 1);
        this._grid.attach (this._switchGrid, 0, 1, 1, 1);
        this._grid.attach (this._cookieLabel, 0, 2, 1, 1);

        // Lägg till rutnätet till fönstret
        this._window.add (this._grid);

        // Visa fönstret och alla dess barnkomponenter
        this._window.show_all();

    }

    _getACookie() {

        // Är kakautomaten påslagen?
        if (this._cookieSwitch.get_active()) {

            // Öka antalet kakor med 1 och uppdatera etiketten
            cookies++;
            this._cookieLabel.set_label ("Antal kakor: " + cookies);

        }

    }

};

// Kör programmet
let app = new GettingTheSignal ();
app.application.run (ARGV);
</code>
    </section>

    <section id="radiobuttonsample">
      <title>Kodexempel med RadioButton</title>
      <media type="image" mime="image/png" src="media/03_jssignal_03.png"/>
      <code mime="application/javascript" style="numbered">#!/usr/bin/gjs

imports.gi.versions.Gtk = '3.0';
const Gtk = imports.gi.Gtk;

// Vi börjar med 0 kakor
var cookies = 0;

class GettingTheSignal {

    // Skapa programmet i sig
    constructor() {
        this.application = new Gtk.Application();

        // Anslut ”activate”- och ”startup”-signaler till återanropsfunktionerna
        this.application.connect('activate', this._onActivate.bind(this));
        this.application.connect('startup', this._onStartup.bind(this));
    }

    // Återanropsfunktion för ”activate”-signal, visar fönstret när den aktiveras
    _onActivate() {
        this._window.present();
    }

    // Återanropsfunktion för ”startup”-signal bygger användargränssnittet
    _onStartup() {
        this._buildUI();
    }

    // Bygg användargränssnittet
    _buildUI() {

        // Skapa programfönstret
        this._window = new Gtk.ApplicationWindow({
            application: this.application,
            window_position: Gtk.WindowPosition.CENTER,
            default_height: 200,
            default_width: 400,
            border_width: 20,
            title: "Välj den som säger ”kaka”!"});

        // Skapa radioknapparna
        this._cookieRadio = new Gtk.RadioButton ({ label: "Kaka" });
        this._notCookieOne = new Gtk.RadioButton ({ label: "Inte kaka",
            group: this._cookieRadio });
        this._notCookieTwo = new Gtk.RadioButton ({ label: "Inte kaka",
            group: this._cookieRadio });

        // Arrangera radioknapparna i sitt eget rutnät
        this._radioGrid = new Gtk.Grid ();
        this._radioGrid.attach (this._notCookieOne, 0, 0, 1, 1);
        this._radioGrid.attach (this._cookieRadio, 0, 1, 1, 1);
        this._radioGrid.attach (this._notCookieTwo, 0, 2, 1, 1);

        // Ställ in knappen högst upp att vara aktiv som standard
        this._notCookieOne.set_active (true);

        // Skapa kakknappen
        this._cookieButton = new Gtk.Button ({
            label: "Få en kaka" });

        // Anslut kakknappen till funktionen som hanterar klickande på den
        this._cookieButton.connect ('clicked', this._getACookie.bind(this));

        // Skapa etiketten
        this._cookieLabel = new Gtk.Label ({
            label: "Antal kakor: " + cookies });

        // Skapa ett rutnät för att arrangera allt inuti
        this._grid = new Gtk.Grid ({
            halign: Gtk.Align.CENTER,
            valign: Gtk.Align.CENTER,
            row_spacing: 20 });

        // Stoppa allting inuti rutnätet
        this._grid.attach (this._radioGrid, 0, 0, 1, 1);
        this._grid.attach (this._cookieButton, 0, 1, 1, 1);
        this._grid.attach (this._cookieLabel, 0, 2, 1, 1);

        // Lägg till rutnätet till fönstret
        this._window.add (this._grid);

        // Visa fönstret och alla barnkomponenter
        this._window.show_all();

    }

    _getACookie() {

        // Valde du ”kaka” istället för ”inte kaka”?
        if (this._cookieRadio.get_active()) {

            // Öka antalet kakor med 1 och uppdatera etiketten
            cookies++;
            this._cookieLabel.set_label ("Antal kakor: " + cookies);

        }

    }

};

// Kör programmet
let app = new GettingTheSignal ();
app.application.run (ARGV);
</code>
    </section>

    <section id="entrysample">
      <title>Kodexempel med Entry</title>
      <media type="image" mime="image/png" src="media/03_jssignal_04.png"/>
      <code mime="application/javascript" style="numbered">#!/usr/bin/gjs

imports.gi.versions.Gtk = '3.0';
const Gtk = imports.gi.Gtk;

// Vi börjar med 0 kakor
var cookies = 0;

class GettingTheSignal {

    // Skapa programmet i sig
    constructor() {
        this.application = new Gtk.Application();

        // Anslut ”activate”- och ”startup”-signaler till återanropsfunktionerna
        this.application.connect('activate', this._onActivate.bind(this));
        this.application.connect('startup', this._onStartup.bind(this));
    }

    // Återanropsfunktion för ”activate”-signal, visar fönstret när den aktiveras
    _onActivate() {
        this._window.present();
    }

    // Återanropsfunktion för ”startup”-signal bygger användargränssnittet
    _onStartup() {
        this._buildUI();
    }

    // Bygg användargränssnittet
    _buildUI() {

        // Skapa programfönstret
        this._window = new Gtk.ApplicationWindow({
            application: this.application,
            window_position: Gtk.WindowPosition.CENTER,
            default_height: 200,
            default_width: 400,
            border_width: 20,
            title: "Stava till ”kaka” för att få en kaka!"});

        // Skapa textinmatningsfältet
        this._spellCookie = new Gtk.Entry ();

        // Skapa kakknappen
        this._cookieButton = new Gtk.Button ({
            label: "Få en kaka" });

        // Anslut kakknappen till funktionen som hanterar klickande på den
        this._cookieButton.connect ('clicked', this._getACookie.bind(this));

        // Skapa etiketten
        this._cookieLabel = new Gtk.Label ({
            label: "Antal kakor: " + cookies });

        // Skapa ett rutnät för att arrangera allt inuti
        this._grid = new Gtk.Grid ({
            halign: Gtk.Align.CENTER,
            valign: Gtk.Align.CENTER,
            row_spacing: 20 });

        // Stoppa allting inuti rutnätet
        this._grid.attach (this._spellCookie, 0, 0, 1, 1);
        this._grid.attach (this._cookieButton, 0, 1, 1, 1);
        this._grid.attach (this._cookieLabel, 0, 2, 1, 1);

        // Lägg till rutnätet till fönstret
        this._window.add (this._grid);

        // Visa fönstret och alla barnkomponenter
        this._window.show_all();

    }

    _getACookie() {

        // Stavade du ”kaka” rätt?
        if ((this._spellCookie.get_text()).toLowerCase() == "kaka") {

            // Öka antalet kakor med 1 och uppdatera etiketten
            cookies++;
            this._cookieLabel.set_label ("Antal kakor: " + cookies);

        }

    }

};

// Kör programmet
let app = new GettingTheSignal ();
app.application.run (ARGV);
</code>
    </section>

  </section>

</page>