package elte.java2_utikalauz5.gui; /** Képernyőn mászkáló kukacszerű egyszerű animáció a megjelenítő metódusok használatának szemléltetésére.

A kukac másodpercenként egyet mozog véletlenszerű irányba, és egérkattintással tetszőleges új helyről is indítható. Amennyiben a kukac feje (piros) nem tud új helyre lépni, vagy nem látszana a képernyőn, akkor új helyről fog indulni. @link.forrásfájl {@docRoot}/../data/gui/src PaintTeszt.java @since Java 2 Útikalauz programozóknak 5.0 */ public class PaintTeszt extends java.awt.event.MouseAdapter implements Runnable, java.awt.event.HierarchyListener { /** A kukacot felépítő négyzetek oldalmérete képpontokban */ private static final int MÉRET = 10; /** A kukacot felépítő négyzetek maximális száma */ private static final int MAXPONT = 20; /** A kukac lépései közti várakozási idő ezredmásodpercben */ private static final long LÉPÉS = 1000; /** A megjelenítésre használt grafikus komponens */ private java.awt.Component vászon; /** Konstruktor a megjelenítésre használt grafikus komponens megadásával. @param vászon A megjelenítésre használt grafikus komponens */ public PaintTeszt( java.awt.Component vászon ) { this.vászon = vászon; vászon.addMouseListener(this); //egérkattintás figyelése a komponensen vászon.setBackground(java.awt.Color.YELLOW); //saját színek beállítása vászon.setForeground(java.awt.Color.BLUE);//a jobb nyomonkövethetőségért vászon.addHierarchyListener( this );//animálás vezérlése a láthatósággal } /** A kukac pontjai */ private java.util.LinkedList pontok = new java.util.LinkedList(); /** Új pont hozzáadása a kukachoz. Valóban új pont hozzáadásakor kéri a szükséges területek újrarajzolását is. @param pont A hozzáadandó új pont @return igaz, ha a megadott pont még nem volt része a kukacnak */ private boolean újpont(java.awt.Point pont) { synchronized( pontok ) { if (pontok.contains(pont)) return false; //már tartalmazott pont pontok.add(pont); //új pont felvétele és megjelenítésének kérése vászon.repaint(pont.x*MÉRET, pont.y*MÉRET, MÉRET, MÉRET); if (pontok.size()>1) { pont = pontok.get(pontok.size()-2);//előző fejpont újraszínezése vászon.repaint(pont.x*MÉRET, pont.y*MÉRET, MÉRET, MÉRET); for (int index = pontok.size()-MAXPONT; --index>=0; ) { pont = pontok.get(index);//túlnyúló pontok törlésének kérése vászon.repaint(pont.x*MÉRET, pont.y*MÉRET, MÉRET, MÉRET); } } } return true; //új pont felvételének jelzése } /** Egérgomb megnyomása. @param egéresemény Az aktuálisan lenyomott gombot reprezentáló esemény */ @Override public void mousePressed(java.awt.event.MouseEvent egéresemény) { java.awt.Point pont = egéresemény.getPoint(); pont.x /= MÉRET; //egérkoordináták átalakítása kukacpontokká if (pont.x>=vászon.getWidth()/MÉRET) return; //ha nem látszik teljesen pont.y /= MÉRET; //akkor nem fogadjuk el if (pont.y>=vászon.getHeight()/MÉRET) return; újpont(pont); //kattintási hely felvétele új kukacpontként }; /** Kukacmozgatást végző programszál */ private Thread mozgató; /** Kukacmozgatás indítása */ public synchronized void start() { if (mozgató!=null) return; //ha már mozog, nincs mit tenni System.out.println("Start: "+(vászon.isDoubleBuffered() ?//megjelenítési "offscreen" : "normál")); //mód kiírása indítási üzenetként mozgató = new Thread(this); //új programszál a mozgatáshoz mozgató.start(); //programszál indítása } /** Kukacmozgatás leállítása */ public synchronized void stop() { mozgató = null; //mozgató programszál felé jelezzük a megállást } /** Animálás indítása és leállítása a vászon láthatóságának változásakor. @param esemény a komponenshierarchia változási eseménye */ public void hierarchyChanged( java.awt.event.HierarchyEvent esemény ) { if ((esemény.getChangeFlags() & java.awt.event.HierarchyEvent. SHOWING_CHANGED)!=0) if (esemény.getComponent().isShowing()) start(); else stop(); } /** Véletlenszámgenerátor a kukacmozgatáshoz */ private java.util.Random véletlen = new java.util.Random(); /** Kukacmozgatás egy lépésének elvégzése */ public void run() { if (java.awt.EventQueue.isDispatchThread()) synchronized(pontok) { java.awt.Point pont = null; int maxx = vászon.getWidth()/MÉRET-1;//maximális látható koordináták int maxy = vászon.getHeight()/MÉRET-1; if (pontok.size()>0) { //folytatás keresése pont = pontok.getLast(); if (pont.x<=maxx && pont.y<=maxy) { java.util.Vector újpontok = //lehetséges new java.util.Vector(8); //folytatások if (pont.x>0) újpontok.add( //balra new java.awt.Point(pont.x-1, pont.y)); if (pont.x0) újpontok.add( //fel new java.awt.Point(pont.x, pont.y-1)); if (pont.y0) {//folytatás keresése/kiválasztása pont = újpontok.elementAt(véletlen.nextInt( újpontok.size())); if (újpont(pont)) return; //megvan a folytatás újpontok.remove(pont); //tovább kell keresni } } } //nem sikerült folyamatos folytatást találni if (maxx>=0 && maxy>=0) { //véletlenszerűen keresünk tovább maxx++; maxy++; int darab = MAXPONT; //próbálkozások számának maximalizálása pont = new java.awt.Point(); do { //véletelen pont keresése pont.x = véletlen.nextInt(maxx); pont.y = véletlen.nextInt(maxy); } while (pontok.contains(pont) && --darab>0); if (újpont(pont)) { //új kezdés System.out.println("új kezdés: "+pont); return; } } //nem találtunk folytatást System.err.println("Nem sikerült a folytatás..."); } else { //léptető programszál while(true) try { Thread.sleep(LÉPÉS); //lépések közti idő kivárása synchronized(this) { //ha már nem kell tovább léptetni if (Thread.currentThread() != mozgató) break;//akkor kilépés } java.awt.EventQueue.invokeLater(this); //léptetés elvégeztetése } catch (Exception e) { break; } } } /** Az utoljára kirajzolt állapot pontjainak végindexe (+1: darabszáma) */ private int maxindex; /** A kukac aktuális állapotának kirajzolása. @param szöveg A kirajzolás oka (paint/update) @param mind Igaz értéke esetén minden pont, hamis esetén csak az eddig meg nem jelenített új pontok kirajzolása. @param töröl Igaz esetén a kukac végén az elhagyott pontok törlése. @param g A megjelenítéshez használt rajzolási környezet. */ public void pontoz( String szöveg, boolean mind, boolean töröl, java.awt.Graphics g ) { System.out.print(szöveg+": "); if (mind) maxindex = 0; //minden pont esetén a kezdőindex nullázása java.awt.Point pont = null; java.awt.Rectangle négyzet = new java.awt.Rectangle(); java.awt.Rectangle vászon = new java.awt.Rectangle( //a látható terület 0, 0, this.vászon.getWidth(), this.vászon.getHeight()); java.awt.Shape vágás = g.getClip(); //a rajzolási környezet vágóterülete int darab = 0; synchronized( pontok ) { int index = pontok.size()-MAXPONT; if (index>0) { //elhagyott pontok törlése maxindex-=index; if (maxindex<0) maxindex=0; while (--index>=0) { pont = pontok.removeFirst(); //pontadatok törlése if (töröl) { //pont megjelenítésének törlése négyzet.setBounds( pont.x*MÉRET, pont.y*MÉRET, MÉRET, MÉRET); if (vászon.intersects(négyzet) && //amennyiben látható (vágás == null || vágás.intersects(négyzet))) { g.clearRect(négyzet.x, négyzet.y,//a terület törlése négyzet.width, négyzet.height); darab++; } } } if (darab>0) { //a törölt pontok számának megjelenítése System.out.print(darab+" pont törölve, "); darab = 0; } } index=pontok.size(); g.setColor(java.awt.Color.RED); //a kezdőpontot kiemelő szín while (index>0 && index >= maxindex) { //pontok megjelenítése pont = pontok.get(--index); négyzet.setBounds(pont.x*MÉRET, pont.y*MÉRET, MÉRET, MÉRET); if (vászon.intersects(négyzet) && //amennyiben látható (vágás == null || vágás.intersects(négyzet))) { g.fillRect(négyzet.x, négyzet.y, //a pont megjelenítése négyzet.width, négyzet.height); darab++; } if (index==pontok.size()-1) //normál rajszín visszaállítása g.setColor(this.vászon.getForeground()); } maxindex=pontok.size(); //megjelenített pontok számának eltárolása } System.out.println(darab+" pont kirajzolva."); } }