Laboration 4 b med smak av grafik, knappar och fönster

Här kommer en steg-för-steg-laboration, där den sista uppgiften ska redovisas tillsammans med svar på frågorna längst ner på sidan. Denna laboration bygger på att du kan söka i Javas klassbibliotek, har tillgång till en lärobok om grafik-hantering i Java eller kan hitta information om detta på nätet, t.ex. i Java Tutorial

Eftersom denna laboration är rykande färsk så vill jag ha återkoppling på den. Vad är svårt att förstå? Hur kan det bli bättre? Vad är bra i instruktionerna? Vad saknas?

  1. Definera en exekverbar klass. Låt main-metoden har följande innehåll:
    javax.swing.JFrame ettFönster = new javax.swing.JFrame();
    javax.swing.JButton enKnapp = new javax.swing.JButton("Push me!");
    ettFönster.getContentPane().add(enKnapp);
    ettFönster.pack();
    ettFönster.setVisible(true);
    
    Vid körning ska följande fönster visa sig:
    Du som kör KDE kan ibland råka ut för att ett fönster "fastnar" under den grå listen överst på bildskärmen. Dra ut ett fönster som "fastnat" där genom att hålla nere "alt"-tangenten och dra ut fönstret med muspekaren. (Klick-dra-släpp, vänster musknapp)

    Försök sedan att lista ut vilken betydelse respektive rad har. Se i boken om du har Java Software Solutions eller någon annan bok som handlar om grafik och java. Se även den utmärkta Java Tutorial. Länk finns på kursens länksida. Det går även bra att ställa frågor till labhandledaren under laborationspass eller med e-post.

    Man kan korta ner skrivsättet i ovanstående kodsnutt genom att starta klassdefinitionen med raden

    import javax.swing.JButton;
    import javax.swing.JFrame;
    
    eller importera hela paketet javax.swing på en gång:
    import javax.swing.*;
    
    Då skulle kodsnutten kunna se ut så här istället:
    JFrame ettFönster = new JFrame();
    JButton enKnapp = new JButton("Push me!");
    ettFönster.getContentPane().add(enKnapp);
    ettFönster.pack();
    ettFönster.setVisible(true);
    

  2. Definiera en klass MyWindow som ärver klassen JFrame. För att ärva JFrame måste klassen importeras till klassdefinitionen:
    import javax.swing.JFrame;
    
    Sedan måste man tala om att klassen MyWindow ska ärva JFrame. Det gör man tillsammans med klassdeklarationen, så här:
    public class MyWindow extends JFrame{
    
    Det innebär alltså att MyWindow utökar JFrame, eller ärver som man också säger. Alla offentliga metoder som finns i JFrame är nu alltså tillgängliga i klassen MyWindow.

  3. Definera en konstruktor i klassen MyWindow. Se läroboken för mer information om konstruktorer. Lägg till nedanstående kodsnutt i konstruktorn i klassen MyWindow:
    JButton minKnapp = new JButton("Push me!");
    this.getContentPane().add(minKnapp);
    this.pack();
    this.setVisible(true);
    
    Kodraderna i konstruktorn exekveras när ett objekt av typen MyWindow skapas. Vad skiljer dessa kodrader åt från kodraderna i uppgift 1? Varför behöver man inte ha med raden JFrame ettFönster = ...? Varför står det this istället för ettFönster?

  4. Skapa en instans av klassen MyWindow från en annan klass Test.java:
    public class Test{
        public static void main(String argv[]){
            MyWindow mittFönster = new MyWindow();
        }
    }
    
    Kompilera och testkör din testklass. Det synliga resultatet bör vara samma som i uppgift 1. Det finns en viktig skillnad som vi ska dra nytta av i senare uppgifter.

  5. Alla har väl hör talesättet tala är silver och tiga är guld. Men vad är det för glädje om någon tiger men inte lyssnar? Nu ska du göra din klass MyWindow till en lyssnare. Detta gör du genom att implementera gränssnittet ActionListener, se java.awt.event.ActionListener. Gör så här:

    1. Importera paketet java.awt.event.
    2. Utöka raden
      public class MyWindow extends JFrame{
      
      till
      public class MyWindow extends JFrame implements ActionListener{
      
    3. Definiera den metod som gränssnittet java.awt.event.ActionListener har, i din klass MyWindow.

    Du har nu definierat en lyssnare! Denna lyssnare kan reagera på knapptryckningar.

  6. Lägg till en lyssnare till din knapp. Detta gör det möjligt att reagera på att någon trycker på knappen. I och med att din klass MyWindow är en lyssnare så lägger du till den till knappen med programsatsen:
    minKnapp.addActionListener(this);
    
    Justera även metoden actionPerformed(ActionEvent evt) så att denna gör en testutskrift till kommandoprompten, så att du får ett kvitto på att din lyssnare fungerar.

    Att fundera över: Varför kan man inte lägga till denna rad till kodsnutten i uppgift 1?

  7. Lägg till ett textfält i ditt program som gör det möjligt att mata in text och visa text för användaren. Se javax.swing.JTextField. För att lägga till ett textfält behövs även en layout så att komponenterna hamnar bredvid varann. Kodraden this.getContentPane().setLayout( new java.awt.FlowLayout()); lägger till en layout som lägger komponenterna i en rad.

  8. Skapa en klass som visar upp ett fönster på bildskärmen. Se bild.

    När man trycker på knappen ska texten på textraden ändras. Vissa tecken ska bytas ut mot andra enligt nedanstående schema:
    1. Alla förekomster av 'a' eller 'A' byts ut mot siffran 4.
    2. Alla förekomster av 'e' eller 'E' byts ut mot siffran 3.
    3. Alla förekomster av 'i' eller 'I' byts ut mot siffran 1.
    4. Alla övriga bokstäver har en femtioprocentig chans att skrivas som stora bokstäver (ni behöver inte kolla om bokstaven redan är versal)
    Resultatet kan då till exempel bli så här:

Några frågor om fönster, knappar och händelser

  1. Beskriv hur ditt program fungerar, rad för rad.
  2. Beskriv vad en lyssnare är för något och vad som gör ett objekt till en lyssnare.
  3. Vad kan man använda en lyssnare till?
  4. Vad är skillnaden att använda en instans av klassen JFrame som i uppgift 1 och en instans av klassen MyWindow i uppgift 5?