Gyakorlati alapok IV.

Végre ablakozunk! (AWT, Swing, JavaFX)

 

Catch me if you can!

 

Ebben a fejezetben továbbfejlesztjük a Játék: Wollen Sie arbeiten? (Akar Ön dolgozni?) című fejezetben megalkotott kódokat és kissé átalakítva belőle egy másik játékot készítünk.

 

Sokan láthatták Spielberg mester Catch me if you can! (Kapj el, ha tudsz!) című mozifilmjét. A játék azonos alapelveket alkalmazva most az lesz, hogy a főablakból egyetlen gombnyomásra induljon el egy olyan kisablakfolyam, amelyet ügyesen kattintgatva mindig be kell zárni! Természetesen a kisablakok mindig máshol, véletlenszerűen jelenjenek meg.

Alapjában véve a program az említett fejezet kódjaiból könnyen felépíthető, azonban itt is belefutottam egy előre nem látott problémába (mert a programozásban legalább ez az egyetlen kiszámíthatatlanság kiszámítható).

 

A buttonAction() függvényben lekezelt WindowInner-objektumok példányosítása és véletlenszerű megjelenítése egy kvázivégtelen ciklusban nem működött vizuálisan megfelelően, mert a JVM csak akkor rajzolta ki véglegesen az objektumokat, amikor a buttonAction() függvény teljesen visszaadta neki a vezérlést. Ez olyan hibajelenségben mutatkozott meg, hogy a kirajzolás ideje alatt kizárólag üres és fehér kisablakok jelentek meg, a különböző színek és az egységes felirat nem. A probléma a kisablakok külön szálakban (A többszálú programozás alapjai (multithread) című fejezetcsomag) való indításánál sem oldódott meg. Nyilvánvaló volt, hogy az időzítéssel kell valamit kezdeni, azaz találni kéne egy olyan rutint, amelyik bár időlegesen visszaadja a vezérlést a JVM-nek, mégis továbblépteti a kisablakok megjelenítését. Meglepetésszerűen ezt a rutint a Timer osztályban találhatjuk meg (A Timer osztály című fejezet).

A megfelelő metódusok megtalálása után a kód már hamar összeállt:

@Override
public void run() {
    new WindowInner();
    }
}

private void buttonAction() {
    Timer timer = new Timer();
    TimerTask task = new WindowInner();
    timer.schedule(task, 0, 1000);
    }
}

 

Mivel a főablak pozícióját nem akartam a véletlenre bízni, a Center osztályt +1 metódussal volt szükséges bővíteni: az egyik az abszolút középre pozicionálásért, a másik a kisablakok véletlenszerű kiszórásáért felel:

 

void setCenter(JFrame frame) {
    Point center = GraphicsEnvironment.getLocalGraphicsEnvironment().getCenterPoint();
    int x = (int) center.getX() - (frame.getWidth() / 2);
    int y = (int) center.getY() - (frame.getHeight() / 2);
    Point ablakCenter = new Point(x, y);
    frame.setLocation(ablakCenter);
}

void setCenterRandom(JFrame frame) {
    Point center = GraphicsEnvironment.getLocalGraphicsEnvironment().getCenterPoint();
    int randomIntX = (int)(Math.random() * 500);
    int randomIntY = (int)(Math.random() * 500);
    int x = (int) center.getX() - (frame.getWidth() / 2) + randomIntX;
    int y = (int) center.getY() - (frame.getHeight() / 2) + randomIntY;
    Point ablakCenter = new Point(x, y);
    frame.setLocation(ablakCenter);
    }
}


Nézzük meg a futtatható Java-kódot:

 

www.informatika-programozas.hu - Futtatható Java-kód!

 

 

 

 

 

 

 


Main.java

 

public class Main {

public static void main(String[] args) {
    Window window = new Window();
    }
}

Center.java

 

import java.awt.*;

import javax.swing.*;

 

public class Center {

 

void setCenter(JFrame frame) {
    Point center = GraphicsEnvironment.getLocalGraphicsEnvironment().getCenterPoint();
    int x = (int) center.getX() - (frame.getWidth() / 2);
    int y = (int) center.getY() - (frame.getHeight() / 2);
    Point ablakCenter = new Point(x, y);
    frame.setLocation(ablakCenter);
}

void setCenterRandom(JFrame frame) {
    Point center = GraphicsEnvironment.getLocalGraphicsEnvironment().getCenterPoint();
    int randomIntX = (int)(Math.random() * 500);
    int randomIntY = (int)(Math.random() * 500);
    int x = (int) center.getX() - (frame.getWidth() / 2) + randomIntX;
    int y = (int) center.getY() - (frame.getHeight() / 2) + randomIntY;
    Point ablakCenter = new Point(x, y);
    frame.setLocation(ablakCenter);
    }
}

 

Window.java

import java.awt.*;
import java.util.Timer;
import java.util.TimerTask;

import javax.swing.*;

class Window extends JFrame {
    JFrame frame = new JFrame();
    JButton button = new JButton("OK!");
    JLabel label = new JLabel();

Window() {
    super();
    button.setBounds(100, 100, 200, 20);
    button.addActionListener(event -> buttonAction());

    label.setBounds(100, 50, 200, 25);
    label.setFont(new Font("Serif", Font.PLAIN, 23));
    label.setText("Catch me if you can!");

    frame.add(button);
    frame.add(label);

    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    Center center = new Center();

    frame.setSize(400, 300);
    frame.setTitle("PJP - Penzes Java Programming");
    center.setCenter(frame);
    frame.setLayout(null);
    frame.setVisible(true);
}

private void buttonAction() {
    Timer timer = new Timer();
    TimerTask task = new WindowInner();
    timer.schedule(task, 0, 1000);
    }
}
 

WindowInner.java

import java.awt.*;
import javax.swing.*;
import java.util.TimerTask;

public class WindowInner extends TimerTask {
    JFrame frameInner = new JFrame();
    JLabel labelInner = new JLabel();

WindowInner() {
    frameInner.add(labelInner);
    frameInner.setDefaultCloseOperation(frameInner.DISPOSE_ON_CLOSE);
    labelInner.setText("HERE I AM!");
    labelInner.setFont(new Font("", Font.BOLD, 16));
    labelInner.setHorizontalAlignment(SwingConstants.CENTER);
    labelInner.setVerticalAlignment(SwingConstants.CENTER);
    Center center = new Center();
    frameInner.setSize(200, 75);
    center.setCenterRandom(frameInner);
    int randomR = (int)(Math.random() * 255);
    int randomG = (int)(Math.random() * 255);
    int randomB = (int)(Math.random() * 255);
    frameInner.getContentPane().setBackground(new Color(randomR, randomG,     randomB));
    frameInner.setVisible(true);
}

@Override
public void run() {
    new WindowInner();
    }
}

 

Végeredmény:

www.informatika-programozas.hu - Catch me if you can!

www.informatika-programozas.hu - Catch me if you can!


Kis gyakorlattal láthatjuk az alkalmazás fogyatékosságait, ezért a játékon elvégezhető további feladatok a következők lehetnek:

Mindezen ötlet implementációja legyen a Tisztelt Olvasó házi feladata!