7. díl - Programování jednoduchých Java GUI her - Časovač

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

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

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
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.


 

Stáhnout

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

 

  Aktivity (1)

Článek pro vás napsal vita
Avatar
vita

Jak se ti líbí článek?
Celkem (5 hlasů) :
4.64.64.64.64.6


 



 

 

Komentáře

Avatar
David Čápka
Tým ITnetwork
Avatar
David Čápka:

Hezky vysvětlené, ten pohyb, souřadný systém atd. Já ty věci beru již jako samozřejmé, ale ony vlastně samozřejmé nejsou. Pokud bys chtěl ušetřit ještě další místo, můžeš metodu timeru implementovat v anonymní třídě, většinou se to tak dělá.

Odpovědět 23.9.2013 17:34
Miluji svou práci a zdejší komunitu, baví mě se rozvíjet, děkuji každému členovi za to, že zde působí.
Avatar
Ala
Neregistrovaný
Avatar
Ala:

Ahoj,

díky za články. Už jsem to pomalu chtěla vzdát s tím, že se nikdy ani ty základy nenaučím, zkoušela jsem i všechny ty gamifikační kurzy, MOOC (tedy, spíš jen UDEMY, to se jako MOOC moc počítat nedá), spoustu návodů, ale je to přeci jen celkem náročné téma na to, aby se mi dařilo zpracovávat informace v angličtině a ještě se něco doopravdy naučit.

Koukám na devbook pár minut a dává mi to naději, že bych možná ještě hůl lámat nemusela :)
No uvidím, mám nepříjemný pocit, že na to prostě nemám mozek a nenaučila by mě to ani učebnice pro prvňáčky, ale zkoušet se to musí.

Ještě jednou za tenhle web dík:)

A.

 
Odpovědět 24.9.2013 23:31
Avatar
czSolomon
Neregistrovaný
Avatar
Odpovídá na Ala
czSolomon:

Naprosto s tebou souhlasím :-)

 
Odpovědět 15.10.2013 16:24
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 3 zpráv z 3.