Informaticasite van het Lauwers College te Buitenpost                 © R.J. van der Beek
 

Hoofdstuk 18 Java

18.2 Interactie

  18.2.1. Knoppen, tekstvensters, radioknoppen (Interactiecomponenten)

We willen nu een programma met daarin interactie met de gebruiker.
We maken een programma waarvan de interface er als volgt uitziet:



Als je op de button met Druk af klikt, en je hebt bijvoorbeeld eerst op de radioknop met Rood geklikt, dan wordt de zin die in het tekstvenster staat onder in het appletvenster met rode letters afgedrukt.

We moeten dus ten eerste een button hebben, waarop Druk af staat.
Die maak je op de volgende manier:
  • Je moet zo'n button eerst declareren: Button btnDrukaf;
  • Dan moet de button echt gemaakt worden (in het geheugen): btnDrukaf = new Button("Druk af!");
  • En dan moet je er nog voor zorgen dat hij echt in beeld komt: this.add(btnDrukaf);
    Die opdracht moet je in de methode init zetten (en de vorige ook). De methode init heeft altijd betrekking op het applet zelf, en this heeft daarom tot gevolg dat de button op het appletvenster geplaatst wordt.
    (eigenlijk moeten we zeggen: add is een methode uit de klasse Applet, en omdat init dat ook is, kan add vanuit init worden aangeroepen met this als object) Het tekenen van een button gebeurt dus niet in de paint-methode maar in de init-methode.
De tweede button wordt op dezelfde manier gemaakt m.b.v. de volgende opdrachten:
Button btnVerkeerd;
btnVerkeerd = new Button("Hier niet klikken!");
add(btnVerkeerd);


Dan willen we daarnaast een tekstvenster. Dat maak je op ongeveer dezelfde manier als een button:
TextField txtZin;
txtZin = new TextField("Typ hier iets in",35);
this.add(txtZin);


Tenslotte willen we nog drie radioknoppen, die bij elkaar horen. Dat doe je ook weer op ongeveer dezelfde manier als een button:
CheckboxGroup radioGroup;
Checkbox radio1;
Checkbox radio2;
Checkbox radio3;
radioGroup = new CheckboxGroup();
radio1 = new Checkbox("Rood", radioGroup,false);
radio2 = new Checkbox("Blauw", radioGroup,true);
radio3 = new Checkbox("Groen", radioGroup,false)
this.add(radio1);
this.add(radio2);
this.add(radio3);


Je hebt nog een aantal methoden nodig om met tekstvensters enz. te kunnen werken.
Wil je de tekst uit een tekstvenster op de één of andere manier gebruiken, dan gebruik je de methode getText(), bijvoorbeeld op de volgende manier: String t = txtZin.getText();

Wil je in een tekstvenster een nieuwe tekst (of geen tekst) plaatsen, dan kan dat bijvoorbeeld zo:
txtZin.setText("zet dit in het tekstvak");
of als je het tekstvenster leeg wilt maken: txtZin.setText("");

Wil je op een button of een label een nieuwe tekst plaatsen, dan kan dat bijvoorbeeld zo:
btnVerkeerd.setLabel("Een nieuwe tekst op een button");

Wil je weten of er op een radioknop geklikt is of niet (dus of er een stip in staat) dan kan dat bijvoorbeeld zo:
boolean k = radio1.getState();
Als er op geklikt is heeft k de waarde true en anders false.

Als je, terwijl het programma loopt, een punt in een radioknop wilt zetten dan kan dat bijvoorbeeld zo:
radio1.setState(true);

Wil je de tekst uit een tekstvenster op het scherm afdrukken, zonder de paint-methode te gebruiken, dan kan dat met behulp van de volgende opdracht (in de methode init):
String t = txtZin.getText();
System.out.println(t);


Hierdoor wordt de tekst van de variabele t afgedrukt, maar niet in het appletvenster. De tekst verschijnt in het DOS-scherm (zie de figuur hier onder). Dit gebruik je eigenlijk alleen als je fouten in je programma wilt opsporen, je kunt dan gemakkelijk met System.out.println( ) de waarde van een variabele, die je niet helemaal vertrouwt, laten afdrukken.

  18.2.2. De lay-out van de knoppen

In de vorige paragraaf hebben we niet aangegeven waar de knoppen precies op het applet geplaatst moeten worden.
Je kunt die plaats op verschillende manieren bepalen.
De gemakkelijkste manier is met de zogenaamde flowlayout-manager. Als je in de init-methode de volgende opdracht plaatst:
this.setLayout(new FlowLayout());
dan worden alle knoppen enz. (die worden in het algemeen besturingselementen genoemd) naast elkaar geplaatst van links naar rechts, zolang er plaats is. Als er geen plaats meer is gaat het er onder verder.
Je kunt het eventueel nog een beetje preciezer aangeven op bijvoorbeeld de volgende manier: this.setLayout(new FlowLayout(FlowLayout.RIGHT, 15, 20));
dan worden ze rechts uitgelijnd, en er wordt horizontaal een tussenruimte van 15 pixels aangehouden, en verticaal een tussenruimte van 20 pixels.

Een andere manier is die m.b.v. de gridlayout-manager. Dan kun je aangeven hoeveel rijen met knoppen je wilt hebben, en hoeveel kolommen.
Als je bijvoorbeeld de volgende opdracht in de init-methode plaatst:
this.setLayout(new GridLayout(2,3));
dan worden er 2 rijen met knoppen gemaakt, en dan zo dat er drie naast elkaar staan.
Je kunt het eventueel nog een beetje preciezer aangeven op bijvoorbeeld de volgende manier: this.setLayout(new GridLayout(2, 3, 15, 20));
dan worden er ook 2 rijen van 3 knoppen gemaakt, en er wordt horizontaal een tussenruimte van 15 pixels aangehouden, en verticaal een tussenruimte van 20 pixels.

Als je zelf precies aan wilt geven waar de knoppen geplaatst moeten worden dan kan dat ook.
Zie daarvoor 18.3.

  18.2.3. Reageren op een knop

Als we willen dat het programma reageert als er op een knop wordt geklikt, dan moeten we dat programmeren.
Als de gebruiker op een button drukt of iets invult in een tekstvenster en dan op enter drukt of een schuifregelaar bedient dan noem je zo'n handeling een event. Je moet het programma zo inrichten dat het aan event-handling (afhandelen van gebruikers-acties) gaat doen.
Om op een event te kunnen reageren moet je in het programma een zogenaamde event-listener in het leven roepen, en die moet je koppelen aan de interactie-component.
Een event-listener is een object dat een seintje krijgt als er wat met de interactie-component gebeurt.
Het koppelen van een event-listener aan een interactie-component gebeurt door aanroep van een methode van de betreffende component. De naam van die methode verschilt per component-type:
- in de klasse Button zit een methode addActionListener
- in de klasse Scrollbar zit een methode addAdjustmentListener

Interactie-componenten, zoals buttons en scrollbars, geven de event-listener die er aan gekoppeld is een seintje zodra de gebruiker daar aanleiding toe geeft. Dat seintje wordt gegeven door een speciale methode van de event-listener aan te roepen:
- Een button roept de methode actionPerformed aan van zijn actionlistener
- Een scrollbar roept de methode adjustmentValueChanged aan van zijn adjustmentlistener.

Dat heeft tot gevolg dat we, om die event-handling te regelen, om vier dingen moeten denken.
Je moet de volgende vier dingen toevoegen aan je programma:
  1. aan het begin een extra package importeren, namelijk: import java.awt.event.*;
  2. in de kopregel vermelden dat het om een interface gaat door implements ActionListener toe te voegen.
    De kop wordt dus:
    public class Oefening3 extends Applet implements ActionListener
  3. de interface koppelen aan de knoppen in de methode init:
    btnDrukaf.addActionListener(this);
    btnVerkeerd.addActionListener(this);
  4. deze interface heeft maar één methode, namelijk: public void actionPerformed (ActionEvent e)
    In die methode staan o.a. de volgende regels:
    if (e.getSource() == btnDrukaf)
            {
                    repaint();
            }

    Dat betekent: als er op de Drukaf-button is geklikt dan moet de methode paint opnieuw worden uitgevoerd.
    En die methode is zo geprogrammeerd dat er al rekening mee gehouden is dat er op bepaalde knoppen kan zijn gedrukt.

  18.2.4. Het volledige programma

import java.awt.*; 
import java.applet.*; 
import java.awt.event.*; 

public class Oefening3 extends Applet implements ActionListener 
{ 

     Button btnDrukaf; 
     Button btnVerkeerd; 
     TextField txtZin; 
     CheckboxGroup radioGroup; 
     Checkbox radio1; 
     Checkbox radio2; 
     Checkbox radio3; 

     public void init()  
     { 
          // We gebruiken FlowLayout 
          this.setSize(700,80);
          this.setLayout(new FlowLayout()); 
          btnDrukaf = new Button("Druk af!"); 
          btnVerkeerd = new Button("Hier niet klikken!"); 
          txtZin = new TextField("Typ hier iets in",35); 
          radioGroup = new CheckboxGroup(); 
          radio1 = new Checkbox("Rood", radioGroup,false); 
          radio2 = new Checkbox("Blauw", radioGroup,true); 
          radio3 = new Checkbox("Groen", radioGroup,false); 
          this.add(btnDrukaf); 
          this.add(btnVerkeerd); 
          this.add(txtZin); 
          this.add(radio1); 
          this.add(radio2); 
          this.add(radio3); 

          // Voeg actionlisteners toe aan de buttons
          btnDrukaf.addActionListener(this); 
          btnVerkeerd.addActionListener(this); 
     } 

     public void paint(Graphics g) 
     { 
          if (radio1.getState()) g.setColor(Color.red); 
          else if (radio2.getState()) g.setColor(Color.blue); 
          else g.setColor(Color.green); 

          g.drawString(txtZin.getText(),30,50); 
     } 

     public void actionPerformed(ActionEvent evt)  
     { 
          if (evt.getSource() == btnDrukaf)
          {
          	repaint(); 
          }

          else if (evt.getSource() == btnVerkeerd)  
          { 
               btnVerkeerd.setLabel("Klik hier niet op!"); 
               txtZin.setText("Dat was de verkeerde knop!"); 
               repaint(); 
          } 
     }  
}


Opgaven.
Maak nu opgave 2 van hoofdstuk 18 (Java)