IT rekvalifikace s garancí práce. Seniorní programátoři vydělávají až 160 000 Kč/měsíc a rekvalifikace je prvním krokem. Zjisti, jak na to!
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

Lekce 7 - Programování jednoduchých Java GUI her - Časovač

V minulé lekci, Programování jednoduchých Java GUI her - Události 2, jsme pokračovali v událostech a ukázali jsme si reakci na stisknutí klávesy.

V dnešním díle rozpohybujeme objekt na JPanelu.

Časovač

Pokud budete chtít vytvořit pohybující se objekt na obrazovce, dosáhnete toho tak, že daný objekt budete vykreslovat a zároveň tomuto objektu posunovat souřadnice. Prostě ho budete postupně vykreslovat na lehce změněné pozice a pokud to vykreslování bude dostatečně rychlé, vznikne dojem, že se objekt posunuje. Abychom toho dosáhli, potřebujeme nějakou smyčku (cyklus), ve kterém bude kód pro pohyb objektu (změna jeho aktuální pozice) a jeho vykreslení, a který se bude v určitém intervalu (například každých 20 milisekund což je 50krát za vteřinu) znovu provádět.

Tohoto lze dosáhnout použitím časovače (timer), který funguje tak, jakoby jste v programu měli neviditelné tlačítko, které se vždy po určitém časovém intervalu samo stiskne a vygeneruje nám známou událost ActionEvent. Je to úplně stejné jako s JButton. Vytvoříme posluchače, který bude implementovat rozhraní ActionListener a do metody actionPerformed(Ac­tionEvent e) umístíme kód, který se má provádět.

import javax.swing.JFrame;

public class ProgramSCasovacem extends JFrame {

    public ProgramSCasovacem() {
        this.setTitle("Časovač");
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        MujPanel panel = new MujPanel();
        this.add(panel);

        this.pack();
        this.setResizable(false);
    }

    public static void main(String[] args) {
        new ProgramSCasovacem().setVisible(true);
    }
}

Na třídě s hlavní oknem programu není nic nového.

import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Timer;

public class MujPanel extends JPanel {
    private JLabel navesti;
    private long citac;

    public MujPanel() {
        this.citac = 0;
        this.setPreferredSize(new Dimension(80, 30));

        navesti = new JLabel();
        this.add(navesti);
        navesti.setText(String.valueOf(citac));

        PosluchacCasovace posluchac = new PosluchacCasovace();
        Timer casovac = new Timer(10, posluchac);
        casovac.start();
    }

    private class PosluchacCasovace implements ActionListener {

        @Override
        public void actionPerformed(ActionEvent e) {
            citac++;
            navesti.setText(String.valueOf(citac));
        }
    }
}
Použití Timeru v Java Swing - Tvorba her v Java Swing

Importy nám jsou známy, jen upozorním, že budeme používat třídu Timer z balíčku javax.swing.Timer (nikoli java.util.Timer).

this.citac = 0;

V konstruktoru inicializujeme proměnnou citac na hodnotu nula.

navesti.setText(String.valueOf(citac));

Text na návěští (štítku) nastavíme na hodnotu proměnné citac (čili na nulu). JLabel požaduje jako parametr textový řetězec, proto hodnoutu proměnné citac, která je číslo (typu long), převedeme na řetězec (metoda String.valueOf()).

PosluchacCasovace posluchac = new PosluchacCasovace();

Vytvoříme objekt, kterému budeme zasílat zprávy.

Timer casovac = new Timer(10, posluchac);

Vytvoříme časovač. První parametr mu říká, po kolika milisekundách má generovat události. Jako druhý parametr mu zadáme posluchače, kterému bude tyto události zasílat.

casovac.start();

A nakonec časovač spustíme.

public void actionPerformed(ActionEvent e) {
    citac++;
    navesti.setText(String.valueOf(citac));
}

Při každém vygenerování události se tato událost zašle zaregistrovanému posluchači, přesněji řečeno je zavolána posluchačova metoda actionPerformed(Ac­tionEvent e). My zde pouze zvýšíme hodnotu proměnné citac o jedna a tuto hodnotu vypíšeme.

O tom jak vzniká iluze pohybu jsme si povídali na začátku. Teď přišel čas na to vysvětlit si souřadnicový systém. Tak jako v matematice, i zde je osa x a osa y. Je tu ale malý rozdíl. Souřadnice začínají v levém horním rohu obrazovky kde x = 0 a y = 0. Hodnota x roste doprava, y dolů. Pokud budete mít monitor s rozlišením 800x600, pozice x = 799, y = 599 bude v dolním pravém rohu a x = 400, y = 300 bude přibližně uprostřed.

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JPanel;
import javax.swing.Timer;

public class MujPanel extends JPanel {
    private String text = "TEXT";
    private int x, y;
    private int smerX, smerY;

    public MujPanel() {
        this.x = 0;
        this.y = 0;
        this.smerX = 1;
        this.smerY = 1;
        this.setPreferredSize(new Dimension(400, 300));
        this.setBackground(Color.green);

        Font font = new Font("Monospaced", Font.BOLD, 40);
        this.setFont(font);

        Timer casovac = new Timer(20, new PosluchacCasovace());
        casovac.start();

    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);

        g.drawString(text, x, y);
    }

    private void move() {
        x += smerX;
        y += smerY;

        if (x >= this.getWidth() || x <= 0) {
            smerX = -smerX;
        }
        if ((y >= this.getHeight()) || (y <= 0)) {
            smerY = -smerY;
        }
    }

    private class PosluchacCasovace implements ActionListener {

        @Override
        public void actionPerformed(ActionEvent e) {
            move();
            repaint();
        }
    }
}
Pohyb objektů v Java Swing pomocí Timeru - Tvorba her v Java Swing
private String text = "TEXT";

Proměnná uchovávající text, který budeme zobrazovat.

private int x, y;

Deklarace dvou proměnných typu int, které budou uchovávat aktuální pozici.

private int smerX, smerY;

Deklarace dvou proměnných typu int, které budou uchovávat aktuální směr pohybu.

Timer casovac = new Timer(20, new PosluchacCasovace());
casovac.start();

Tento zápis odpovídá předchozímu, jen ušetříme jeden řádek a nemusíme vymýšlet název pro proměnnou typu PosluchacCasovace. Je vytvořen nový Timer, který bude generovat události každých dvacet milisekund a jako posluchače si registruje objekt PosluchacCasovace, který je vytvořen pomocí new.

public void paintComponent(Graphics g) {
    super.paintComponent(g);

    g.drawString(text, x, y);
}

Vykreslí pozadí a text s počátkem na pozici x, y. Tato metoda se volá při prvotním vytvoření JPanelu a také se volá pokaždé, když voláme metodu repaint().

private void move() {
    x += smerX;
    y += smerY;

    if (x >= SIRKA || x <= 0) {
        smerX = -smerX;
    }
    if ((y >= VYSKA) || (y <= 0)) {
        smerY = -smerY;
    }
}

Aktuální x-ová pozice se posune o hodnotu v proměnné smerX (x = x + smerX). Totéž se stane s y-novou souřadnicí. V případě, že by x (to jest počátek textu) bylo větší než velikost panelu (nebo menší), proměnná smerX se změní na opačnou a text se začne pohybovat v opačném x-ovém směru. Obdobné je to pro y-novou souřadnici, kde se kontroluje, zda není větší (menší) než výška panelu.

private class PosluchacCasovace implements ActionListener {

    @Override
    public void actionPerformed(ActionEvent e) {
        move();
        repaint();
    }
}

Pokud je vygenerována událost, objekt (v tomto případě Timer), který ji vygenerovat, se podívá, zda má zaregistrovaného nějakého posluchače. Pokud ano, zavolá posluchačovu metodu actionPerformed(Ac­tionEvent e), ve které je uvedeno, co se má v takovémto případě provést.

V našem příkladě je volána metoda move(), která změní souřadnice x a y o jeden bod a pak se volá metoda repaint(), která zavolá metodu paint(), která pak zavolá metody intComponent(), paintBorder(), and paintChildren(). Abych to zkrátil. Zavoláním metody repaint() se zavolá i naše metoda paintComponent() a tím se provede vše, co jsme do ní nadefinovali.

V příští lekci, Programování jednoduchých Java GUI her - Časovač 2, budeme pokračovat v pohybu objektů po JPanelu.


 

Měl jsi s čímkoli problém? Stáhni si vzorovou aplikaci níže a porovnej ji se svým projektem, chybu tak snadno najdeš.

Stáhnout

Stažením následujícího souboru souhlasíš s licenčními podmínkami

Staženo 336x (2.5 kB)
Aplikace je včetně zdrojových kódů v jazyce Java

 

Předchozí článek
Programování jednoduchých Java GUI her - Události 2
Všechny články v sekci
Tvorba her v Java Swing
Přeskočit článek
(nedoporučujeme)
Programování jednoduchých Java GUI her - Časovač 2
Článek pro vás napsal vita
Avatar
Uživatelské hodnocení:
15 hlasů
vita
Aktivity