2
Tvorba interaktivních grafických programů
Studijní cíl Tento blok je věnován vytváření interaktivních grafických programů. Podrobně bude vysvětleno, jakým způsobem je možno programově reagovat na události myši a klávesnice. Jedná se především o zjištění aktuální polohy myši, detekci pohybu, detekci stisknutí a uvolnění tlačítka myši, rozlišení události od levého nebo pravého tlačítka myši a další.
Doba nutná k nastudování
4 hodiny
Průvodce studiem Při studiu tohoto bloku se předpokládá, že student ovládá základy programování v jazyce Java a je schopen vytvářet jednoduché aplikace s využitím grafického uživatelského rozhraní a jednoduché grafické programy s využitím standardních grafických metod třídy Graphics.
2.1 Interaktivní grafika V předchozích dvou blocích bylo vysvětleno jak vytvářet aplikace s využitím grafického uživatelského rozhraní a jak realizovat vlastní grafický výstup na výstupním zařízení (monitoru). Co však doposud těmto programům chybí je možnost reagovat na události myši a klávesnice. Přitom některé grafické úlohy jsou na této interaktivitě přímo založeny. Jedná se například o možnost zadat pomocí kliknutí a tažení myší počáteční a koncový bod úsečky, vyznačit určitou oblast rastrového obrázku, která bude následně modifikována, získat barvu z určitého pixelu v rastrovém obrázku, definovat nebo modifikovat řídící body křivky, která má být vykreslena, zobrazovat souřadnice kurzoru myši atd. K vyřešení těchto úloh je třeba dokázat detekovat jednotlivé události, které souvisí s činností myši, případně i klávesnice a dokázat na ně adekvátním způsobem reagovat. KST/IPOGR Počítačová grafika
1-1
Petr Veselý KST FEI Univerzita Pardubice
2.2 Události myši Jak bylo naznačeno v bloku 1, k jednotlivým událostem vždy existuje tzv. posluchač (Listener), což je Třída, která implementuje příslušné rozhraní a tuto třídu je potřeba zaregistrovat u příslušné komponenty, jejíž určitou událost je třeba monitorovat. Princip detekování událostí, souvisejících s činností myši, je stejný jako u událostí souvisejících s akcemi okna, respektive komponenty. Při práci s myši jsou k dispozici události MouseEvent reaguje na události stisku a uvolnění tlačítek myši, případně umístění kurzoru myši nad plochy komponenty; MouseMotionEvent reaguje na události související s pohybem myši; MouseWheelEvent reaguje na práci s kolečkem myši Pro každou z uvedených událostí je k dispozici odpovídající listener (respektive objekt implementující odpovídající rozhraní) a každá událost má vlastní sadu obslužných metod pro jednotlivé činnosti. 2.2.1 Práce s tlačítky myši Událost MouseEvent Rozhraní MouseListener Obslužné metody: mouseClicked() obsluha kliknutí (stisk a uvolnění levého tlačítka myši) mouseEntered() obsluha vstupu kurzoru myši nad plochu komponenty mouseExited() obsluha události, kdy kurzor myši opustí plochu komponenty mousePressed() obsluha události stisknutí tlačítka myši mouseReleased() obsluha uvolnění tlačítka myši 2.2.2 Pohyb myši Událost MouseMotionEvent Rozhraní MouseMotionListener KST/IPOGR Počítačová grafika
1-2
Petr Veselý KST FEI Univerzita Pardubice
Obslužné metody: mouseMotionDragged() obsluha události tažení myší (pohyb se stisknutým tlačítkem) mouseMotionMoved() obsluha pohybu myši, pokud není stisknuto žádné tlačítko 2.2.3 Práce s rolovacím kolečkem myši Událost MouseWheelEvent Rozhraní MouseWheelListener Obslužné metody: mouseWheelMoved() obsluha otočení rolovacím kolečkem myši
2.3 Registrování posluchače Existují dvě možnosti, jak zaregistrovat pro danou komponentu příslušného posluchače. V následujícím příkladu budeme registrovat posluchače pro události myši, proto použijeme metodu addMouseListener() a jako parametr uvedeme buď instanci třídy MouseListener nebo MouseAdapter(). 2.3.1 Varianta Listener V tomto případě je potřeba implementovat všechny metody rozhraní daného posluchače. To se jeví jako nevýhoda především tehdy, pokud registrujeme posluchače s více metodami v rozhraní a přitom plánujeme použít pouze některé z nich. V následujícím kódu je ukázka situace, kdy cílem je vykreslit kružnici o poloměru 10 pixelů tak, aby její střed byl v místě kliknutí libovolným tlačítkem myši. Při registraci byl použit příslušný listener (MouseListener) a kromě smysluplné implementace obslužné metody MousePresed bylo nutné zcela zbytečně (prázdný příkaz) implementovat i všechny zbývající metody rozhraní.
KST/IPOGR Počítačová grafika
1-3
Petr Veselý KST FEI Univerzita Pardubice
addMouseListener(new MouseListener() { public void mouseClicked(MouseEvent e) { ; } public void mousePressed(MouseEvent e) { Graphics g = getGraphics(); g.drawOval(e.getX()-10, e.getY()-10, 20, 20); } public void mouseReleased(MouseEvent e) { ; } public void mouseEntered(MouseEvent e) { ; } public void mouseExited(MouseEvent e) { ; } }); Kód 1: Použití třídy XXXListener při registraci posluchače
2.3.2 Varianta Adapter V tomto případě stačí implementovat pouze jednu nebo více požadovaných metod rozhraní daného posluchače. Třída MouseAdapter již implementovala všechny metody rozhraní (prázdné tělo). To je výhodné tehdy, pokud jako v tomto případě potřebujeme obsluhu pouze jedné události. addMouseListener(new MouseAdapter() { @Override public void mousePressed(MouseEvent e) { Graphics g = getGraphics(); g.drawOval(e.getX()-10, e.getY()-10, 20, 20); } }); Kód 2: Použití třídy XXXAdapter při registraci posluchače
KST/IPOGR Počítačová grafika
1-4
Petr Veselý KST FEI Univerzita Pardubice
2.4 Parametr obslužných metod Jednotlivé obslužné metody mají jeden parametr, jehož typ se liší podle typu posluchače (události). Pro události myši MouseEevent a MouseMotionEvent je použit typ parametru MouseEvent, případně pro událost MouseWheelEvenet je to parametr typu WheelEvent. Tento parametr obsahuje důležité informace o poloze myši, kde se událost stala, stisknutém tlačítku, které událost vyvolalo, případně o směru otočení rolovacího kolečka. Důležité metody: getX(), getY(), getPoint() určují polohu kurzoru myši v okamžiku události getButton() specifikují tlačítko, které událost vyvolalo getModifiers(), getModifiersEx() určují, jaký je stav dalších tlačítek myši isAltDown(), isControlDown(), isShiftDown() určují, zda v okamžiku události byly stisknuty klávesy Alt, Control nebo Shift.
2.5 Příklady 2.5.1 Zobrazení polohu myši při každém jejím pohybu Souřadnice jsou zjištěny pomocí metody getX() a getY() parametru typu MouseEvent. Následně jsou převedeny do textové podoby a zobrazeny jako text v příslušné komponentě typu JLabel. private void formMouseMoved(MouseEvent e) { labelSouradnice.setText(e.getX() + " : " + e.getY()); } Kód 3: Ukázka zobrazení souřadnic myši
2.5.2 Rozlišení pravého a levého tlačítka myši Větvení je provedeno na základě návratové hodnoty metody getButton(), která může nabývat hodnot MouseEvent.BUTTON1 (levé tlačítko),
KST/IPOGR Počítačová grafika
1-5
Petr Veselý KST FEI Univerzita Pardubice
MouseEvent.BUTTON2 (střední tlačítko) nebo MouseEvent.BUTTON3 (pravé tlačítko). Dle tlačítka se vykreslí buď kružnice nebo čtverec. private void formMousePressed(MouseEvent e) { Graphics g = getGraphics(); switch (e.getButton()) { case MouseEvent.BUTTON1 : g.drawOval(e.getX()-10, e.getY()-10, 20, 20); break; case MouseEvent.BUTTON3 : g.drawRect(e.getX()-10, e.getY()-10, 20, 20); break; } g.dispose(); } Kód 4: Ukázka volby dle tlačítka
2.5.3 Rozlišení klávesy CTRL Větvení je provedeno na základě návratové hodnoty metody isControlDown(). Pokud byla během stisknutí libovolného tlačítka myši již stisknuta klávesa CTRL, kreslí se kružnice, jinak se vykreslí kruh. private void formMousePressed(MouseEvent e) { Graphics g = getGraphics(); if (evt.isControlDown()) { g.drawOval(e.getX()-10, e.getY()-10, 20, 20); } else { break; g.fillOval(e.getX()-10, e.getY()-10, 20, 20); } g.dispose(); } Kód 5: Ukázka volby dle klávesy CTRL
2.5.4 Kontrola tlačítek myši při události tažení Při tažení se stisknutým středním tlačítkem je kreslena volná čára od ruky. Vždy při každém posunu je vykreslena úsečka od minulé pozice myši. Při události tažení nelze kontrolovat tlačítko myši pomocí metody getButton(), neboť toto tlačítko nevyvolalo událost tažení. Kontrola je řešena pomocí metody getModifiersEx(), v jejíž návratové hodnotě jsou zkombinovány bitové příznaky všech akutálně stisknutých tlačítek myši. Pokud návratová hodnota metody getModifiersEx() obsahuje bitový příznak MouseEvent.BUTTON2_DOWN_MASK, potom je tlačítko stisknuto.
KST/IPOGR Počítačová grafika
1-6
Petr Veselý KST FEI Univerzita Pardubice
private void formMouseDragged(MouseEvent e) { Graphics g = getGraphics(); if ((e.getModifiersEx() & (MouseEvent.BUTTON2_DOWN_MASK)) == MouseEvent.BUTTON2_DOWN_MASK) { g.drawLine(zacatek.x, zacatek.y, e.getX(), e.getY()); zacatek = e.getPoint(); } g.dispose(); } Kód 6: Ukázka kontroly tlačítek myši během události tažení
Otázky na procvičení 1. 2. 3. 4. 5. 6. 7. 8. 9. 10.
Jak se registruje událost u příslušné komponenty? Jaký je rozdíl při registrování pomocí adaptéru a pomocí listeneru? Co je to rozhraní? Jaké jsou události myši? Jaké jsou události klávesnice? Co je to událost, listener a obslužná metoda? Jaké údaje obsahuje parametr u obslužných metod pro události myši? Jak se rozlišuje tlačítko myši, které událost vyvolalo? Jak se kontrolují současně další stisknutá tlačítka? Jak fungují operátory bitového součtu a součinu?
Odkazy a další studijní prameny
http://owebu.bloger.cz/Programovani/Java-Grafika-59-dil http://java.sun.com/docs/books/tutorial/2d/index.html http://www.linuxsoft.cz/article.php?id_article=244 Herout, P. Java a grafické uživatelské prostředí. České Budějovice : Koop, 2007.
KST/IPOGR Počítačová grafika
1-7
Petr Veselý KST FEI Univerzita Pardubice