lu.se

Datavetenskap

Lunds Tekniska Högskola

Denna sida på svenska This page in English

Mer om SimpleWindow och getAdvancedControls

I SimpleWindow finns en metod getAdvancedControls(), som ger dig ett WindowControls-objekt. Med detta kan du göra mer avancerade saker med ditt fönster. Följande exempel demonstrerar detta.

Ändra storlek på texten i fönstret

På de markerade raderna (<=====) visas hur du får fram ett WindowControls-objekt och använder det för att byta storlek och typsnitt för texten i fönstret.

import java.awt.Color;
import java.awt.Font;

import se.lth.cs.pt.window.SimpleWindow;
import se.lth.cs.pt.window.WindowControls;

public class FontDemo {

    public static void main(String[] args) {
        SimpleWindow w = new SimpleWindow(600, 600, "FontDemo");
        
        WindowControls controls = w.getAdvancedControls();   // <====
        
        w.moveTo(100, 100);
        w.writeText("default text");
        
        controls.setFontSize(24);                            // <====
        w.moveTo(100, 200);
        w.writeText("larger text, default font");
        
        controls.setFontName(Font.SERIF);                    // <====
        controls.setFontSize(40);                            // <====
        w.moveTo(100, 300);
        w.writeText("even larger Times Roman");
        
        w.setLineColor(Color.RED);
        w.moveTo(100, 400);
        w.writeText("also available in red");
    }

}

Läsa in text från SimpleWindow

Detta exempel visar hur man kan använda metoden input() för att låta användaren mata in text i ett SimpleWindow.

import se.lth.cs.pt.window.SimpleWindow;
import se.lth.cs.pt.window.WindowControls;

public class InputDemo {

    public static void main(String[] args) {
        SimpleWindow w = new SimpleWindow(600, 300, "InputDemo");

        WindowControls controls = w.getAdvancedControls();  // <====

        while (true) {
            w.moveTo(250, 250);
            w.writeText("Klicka!");

            w.waitForMouseClick();
            w.clear();

            w.moveTo(130, 250);
            w.writeText("Skriv ditt namn nedan.");

            String s = controls.input();                    // <====
            w.clear();

            w.moveTo(30, 100);
            w.writeText("Hej " + s + ".");
        }
    }

}

Att vänta på knapptryckningar med time-out

Detta exempel visar hur man kan vänta på knapptryckningar med time-out. Metoden returnerar en indikation på hur det gick: antingen WindowControls.KEY_EVENT, vilket betyder att användaren tryckt på en knapp, eller WindowControls.TIMEOUT_EVENT, vilket betyder att timern istället gick ut. På detta sätt kan man göra interaktiva spel, som Tangentbordspanik nedan.

import java.util.Random;

import se.lth.cs.pt.window.SimpleWindow;
import se.lth.cs.pt.window.WindowControls;

public class Tangentbordspanik {

    public static void main(String[] args) {
        SimpleWindow w = new SimpleWindow(600, 300, "Tangentbordspanik");

        WindowControls controls = w.getAdvancedControls();    // <====
        controls.setFontSize(24);                             // <====

        Random rand = new Random();

        int correct = 0, incorrect = 0, timeouts = 0;

        while (true) {
            w.clear();
            w.moveTo(50, 50);
            w.writeText("correct: " + correct + "   incorrect: " + incorrect + "   timed out: " + timeouts);

            int n = rand.nextInt(26);
            char hemlis = (char) (n + 'a');

            w.moveTo(250, 200);
            w.writeText("" + hemlis);

            // användaren får 1000ms på sig att trycka på en tangent
            int ev = controls.waitForUserInput(1000);         // <====

            if (ev == WindowControls.KEY_EVENT) {             // <====
                // användaren tryckte på en tangent inom tiden
                if (w.getKey() == (n + 'a')) {
                    correct++;
                } else {
                    incorrect++;
                }

            } else if (ev == WindowControls.TIMEOUT_EVENT) {  // <====
                // användaren tryckte inte på någon tangent inom tiden
                timeouts++;
            }
        }
    }
}

Att undvika flimmer i animationer

Man kan skapa animationer genom att rita nya saker i fönstret med en lagom liten fördröjning emellan. (Du prövar detta själv i exempelvis laboration 2.) Ibland kan sådana animationer, särskilt komplexa sådana, ge upphov till flimmer. Problemet beror på att fönstrets innehåll periodiskt uppdateras på skärmen, och om en sådan uppdatering sker medan programmets uppritning pågår flimrar en halvfärdig bild förbi.

Följande exempel visar hur man kan stänga av automatisk uppdatering. Då får man istället själv ange när i programmet uppdateringen ska göras. Det sker lämpligen då man ritat ut en hel bild.

Om man tar bort raderna med // <===== flimrar animeringen tydligt.

import java.awt.Color;

import se.lth.cs.pt.window.SimpleWindow;
import se.lth.cs.pt.window.WindowControls;

public class FlyingSquare {

    private static void fillSquare(SimpleWindow w, int x, int y, int side, Color col) {
        w.setLineColor(col);
        for (int i = -side / 2; i < side / 2; i++) {
            w.moveTo(x - side / 2, y + i);
            w.lineTo(x + side / 2, y + i);
        }
    }
    
    public static void main(String[] args) {
        SimpleWindow w = new SimpleWindow(500, 200, "Animation");
        WindowControls control = w.getAdvancedControls();                    // <=====

        control.setAutoUpdate(false);                                        // <=====

        while (true) {
            for (int i = 0; i < 360; i++) {
                int x = 250 + (int) (200 * Math.cos(Math.toRadians(i)));
                int y = 70 + (int) (50 * Math.sin(Math.toRadians(3 * i)));
                int side = 40 + (int) (30 * Math.sin(Math.toRadians(3 * i)));
                int intensity = 100 - (int) (100 * Math.sin(Math.toRadians(3 * i)));
                fillSquare(w, x, y, side, new Color(255, intensity, intensity));

                control.update();                                            // <=====

                SimpleWindow.delay(10);
                fillSquare(w, x, y, side, Color.WHITE);
            }
        }
    }

}

Att använda "Sprites" (rörliga grafiska figurer)

Detta exempel visar hur man kan lägga till en grafisk figur, baserad på en bildfil (exempelvis i .png-format). Figuren kan flyttas och roteras. (Namnet "Sprite" härstammar från forna tiders hemdatorer.)

import se.lth.cs.pt.window.SimpleWindow;
import se.lth.cs.pt.window.Sprite;
import se.lth.cs.pt.window.WindowControls;

public class SpriteLoop {

    public static void main(String[] args) {
        SimpleWindow w = new SimpleWindow(600, 600, "SpriteLoop");
        WindowControls controls = w.getAdvancedControls();                // <=====
        
        Sprite s
            = new Sprite("/Lab05-turtle/resources/turtle.png", 50, 50); // <=====
        controls.addSprite(s);                                            // <=====

        while (true) {
            for (int i = 0; i < 360; i++) {
                int x = (int) (300 + 200 * Math.cos(Math.toRadians(i)));
                int y = (int) (300 - 200 * Math.sin(Math.toRadians(i)));
                s.moveMidTo(x, y);                                        // <=====
                s.setDirection(i);                                        // <=====
                SimpleWindow.delay(5);
            }
        }
    }

}

Fullskärm (ej Linux)

Varning: innan du prövar detta, se till att du vet hur du avslutar ett program från tangentbordet (Alt-F4 på Windows, Cmd-Q på Mac). Ett program i fullskärmsläge kan nämligen endast avslutas på detta sätt, såvida det inte självmant avslutar sig genom att returnera från main eller anropa System.exit.

När du skapar ett SimpleWindow anger du en rubrik i konstruktorns tredje parameter. Om du anger rubriken "FULLSCREEN" (exakt så, i versaler) kommer programmet att köra i fullskärmsläge, dvs utan några andra fönster, menyer eller annat.

Du kan pröva detta i exempelvis InputDemo ovan. Då ändrar du raden där fönstret skapas till

        SimpleWindow w = new SimpleWindow(600, 300, "FULLSCREEN");

Programmet tar över hela skärmen, så inga fönster syns. När programmet avslutas kommer fönstren tillbaka.

OBS: Detta fungerar inte riktigt tillfredsställande i Linux, eftersom där inte finns någon universell teknik för fullskärmskörning i Java.