Currently, Java ME is mainly used for games. Especially there it is very important to know how to handle the low level graphics facilities that are available in Java ME. This includes directly drawing to the screen as well as handling key input yourself. Most major applications also implement their own user interface themselves instead of using the high level UI provided by Java ME. The first challenge of this module is a simply key code analyzer so that you can familiarize yourself with the concepts of the Canvas and event processing. The second challenge is more sophisticated and requires you to write a small paint application.
Contents:
* Canvas
* Key Events
* Game Actions
* Geometry and Text
* Images
* PNG Optimization
2. Disclaimer These slides are provided free of charge at http://www.symbianresources.com and are used during Java ME courses at the University of Applied Sciences in Hagenberg, Austria at the Mobile Computing department ( http://www.fh-ooe.at/mc ) Respecting the copyright laws, you are allowed to use them: for your own, personal, non-commercial use in the academic environment In all other cases (e.g. for commercial training), please contact andreas.jakl@fh-hagenberg.at The correctness of the contents of these materials cannot be guaranteed. Andreas Jakl is not liable for incorrect information or damage that may arise from using the materials. This document contains copyright materials which are proprietary to Sun or various mobile device manufacturers, including Nokia, SonyEricsson and Motorola. Sun, Sun Microsystems, the Sun Logo and the Java™ Platform, Micro Edition are trademarks or registered trademarks of Sun Microsystems, Inc. in the United States and other countries. Andreas Jakl, 2009 2
3. Contents Low Level Graphics Canvas Key Events Geometry & Text Images Andreas Jakl, 2009 3
4. Hierarchy of Displayables Andreas Jakl, 2009 Display One Display instance / MIDlet Available in all sub-classes of Displayable Command Displayable Methods for drawing to a canvas Canvas Screen Ticker Graphics TextBox Form List Alert Item Spacer CustomItem Choice (Interface) ChoiceGroup StringItem DateField ImageItem TextField Gauge 4
5. Canvas Canvas = base class Derive your own class from Canvas Canvas assigned to the screen like high level UI can be mixed with high level UI! Functionality: Key events (key codes) Pointer events Paint (must be implemented) Visible / invisible Query properties Andreas Jakl, 2009 5
6. Example: Canvas – Quick Overview Andreas Jakl, 2009 6 public class RealReplayMIDletextendsMIDlet { private booleaniFirstStart = true; private MenuCanvasiMainCanvas; publicRealReplayMIDlet() { } protected void startApp() { // Startapp also gets called when the midlet gains foreground again // -> Only initialize everything in the very first start-up. if (iFirstStart) { iMainCanvas = newMenuCanvas(this); // Create the main canvas Display.getDisplay(this).setCurrent(iMainCanvas); // Activate the canvas iFirstStart = false; } } publicvoidpauseApp() { } publicvoiddestroyApp(boolean unconditional) { } public void exit() { destroyApp(true); notifyDestroyed(); } }
7. Example: Canvas – Quick Overview Andreas Jakl, 2009 7 public class MenuCanvasextends Canvas { privateRealReplayMIDletiMidlet; private intiWidth; private intiHeight; publicMenuCanvas(RealReplayMIDletaMidlet) { iMidlet = aMidlet; // Needed to quit the game setFullScreenMode(true); // Activate full screen mode iWidth = getWidth(); // Query screen size iHeight = getHeight(); } public void paint(Graphics aGraphics) { // Draw background aGraphics.setColor(255, 255, 255); aGraphics.fillRect(0, 0, iWidth, iHeight); // [...] } protected void keyPressed(intaKeyCode) { // Process key events [...] repaint(); } }
8. The Life of a Canvas Andreas Jakl, 2009 8 Canvasconstructor display.setCurrent(myCanvas) showNotify() paint() … events … keyPressed() pointerPressed() display.setCurrent(myForm) hideNotify()
10. Canvas – Full Screen setFullScreenMode(false); setFullScreenMode(true); Andreas Jakl, 2009 10
11. Canvas – Show and Hide showNotify() Is called directly before Canvas becomes visible For initialization, e.g. (re)starting a timer hideNotify() Called after becoming invisible Free resources, cancel timers and threads, ... Also called by the AMS when system screens (e.g., incoming call) are displayed on top Query visibility: Displayable.isShown() Andreas Jakl, 2009 11
12. Canvas – Events Events sent to (visible) Canvas Calls methods defined in Canvas base class Key- & pointer-events, commands Serial event delivery No second event is sent before first event is handled (= you left the event handling method) Exception: repaint enforced by you Andreas Jakl, 2009 12
13. Key Events keyPressed(intkeyCode) When a key is pressed down keyRepeated(intkeyCode) Called again and again when the key is held down Frequency depends on mobile phone better: use an own timer until … keyReleased(intkeyCode) When the key is released Andreas Jakl, 2009 13 keyPressed() keyRepeated() keyReleased()
15. Key Codes – Game Actions Phones: no standardized key layout Therefore: game actions – appropriate keys for each phone intgetGameAction (intkeyCode) Andreas Jakl, 2009 15 Defined in the Canvasclass
16. Key Codes – Example Andreas Jakl, 2009 16 protected void keyPressed(intkeycode) { SimplePlayerGUIgui = getGUI(); switch (keycode) { // This variant does not allow handling multiple simultaneous keypresses case Canvas.KEY_NUM1: // (which are not supported by many phones) // Jump backward gui.skip(true); break; caseCanvas.KEY_NUM2: gui.togglePlayer(); break; // [...] caseCanvas.KEY_POUND: gui.changeVolume(false); break; default: // Handle both keys and game actions – keys first, as they might be game actions as well intgameAction = getGameAction(keycode); if (gameAction == Canvas.RIGHT) { // Jump forward gui.skip(false); // [...] } elseif (gameAction == Canvas.FIRE) { gui.togglePlayer(); } } Adapted from the Sun WTK 2.5.2. MobileMediaAPI-examle
17. Canvas – Soft Keys, … Problem: MIDP 2.0 does not define keycode constants for softkeys, delete, ... Different keycodesfor every manufacturer Solutions: Use Commands (problematic: high level menu doesn’t fit to your design!) Compile an own version for every manufacturer Use generic ‘translation’-method – within certain limits Example – left softkeykeycode: -6 (Nokia), -1 (Siemens), -21 (Motorola), 21 (Motorola) Andreas Jakl, 2009 17
18. Canvas – Paint If repaint is necessary (e.g. info dialog was on top of MIDlet) Framework calls Canvas.paint() Request repaint yourself Call: repaint() Optional: specify region paint()will be called automatically andasynchronously, at a “fitting” moment Double Buffering Usually supported and activated Query: booleandblBuf = canvas.isDoubleBuffered(); If not: create off-screen bitmap yourself Andreas Jakl, 2009 18 void keyPressed(int aKeyCode) { // Process key events [...] repaint(); } paint() not called instantly; usually through an extra thread void paint(Graphics g) { // Draw... }
20. Graphics Graphics-object sent to paint() as a parameter Provides methods for drawing of: Line (SOLID or DOTTED) Rectangle (also filled and/or with rounded corners) Arc (part of an ellipse, also filled) Triangle (also filled) Text Images Andreas Jakl, 2009 20 void paint(Graphics g) { // Draw... }
21. Colours Colour is used for all drawing operations that follow (including text) g.setColor(int red, int green, int blue); Usually no 32 bit display: Automatic assignment of nearest displayable colour no colour fidelity Andreas Jakl, 2009 21 void paint(Graphics g) { g.setColor(255, 255, 255); // White g.fillRect(0, 0, getWidth(), getHeight()); // Fill the whole background g.setColor(255, 0, 0); // Red g.drawLine(5, 5, 250, 250); // Centered text g.drawString("Hello", getWidth() / 2, getHeight() / 2, Graphics.HCENTER|Graphics.BASELINE); }
23. Example: g.drawString(“Mopius”, 0, 0, Graphics.HCENTER|Graphics.BASELINE); Canvas Text – Positioning Andreas Jakl, 2009 23 Mopius g.drawString(“Mopius”, 0, 0, Graphics.LEFT|Graphics.TOP); Mopius
24. Recap: OR Andreas Jakl, 2009 24 OR executed for corresponding bits of two values Overview: OR Both values that were combined withor can be retrieved later on Baseline is contained in the combined value!
25. Text – Font Choose through Font-object, then assign to Graphics-obj. Request font based on criteria: Face: monospace, proportional, system Style: plain, bold, italic, underlined Size:large, medium, small Example: Font titleFont = Font.getFont(Font.FACE_SYSTEM, Font.STYLE_BOLD|Font.STYLE_ITALIC, Font.SIZE_LARGE);g.setFont(titleFont);g.drawString(“Test”, 0, 0, Graphics.TOP|Graphics.LEFT); Andreas Jakl, 2009 25
26. Text – Font Sun WTK Nokia Series 40 (Emulator) Andreas Jakl, 2009 26 … mostgamesusetheirownbitmapfonts!
30. Images Main image format for JavaME (must be supported): .png (Portable Network Graphics) Similar to .gif (which was patented until 2003 because of its LZW compression) Features: Compression: works well for graphics, not so well for photos Transparency: support depends on device – 1 bit transparency or full alpha-channel. Query:int levels = [Display].numAlphaLevels() Usually used for phones:8 bit colour depth (file size), 1 bit transparency (compatibility) Andreas Jakl, 2009 30
31. Save PNGs – File Size Reduction Optimized export – Photoshop: Save for Web Further optimization – Pngcrush:http://pmt.sourceforge.net/pngcrush/ Andreas Jakl, 2009 31 Use as few colors as possible (fine gradients compress worse) No dithering (compression gets more difficult) Transparenter Kanal kann gesetzt werden You can set a transparency channel
32. PNG Optimization – Example: 472 x 472 px Andreas Jakl, 2009 32 256 colours, no dither 30,0 kB 64 colours, no dither 16,3 kB 8 colours, no dither 6,3 kB Results: - Not much difference between 256 and 64 colours (especially on a device display), but only half of the file size - Limits of optimization: 8 colours not enough - Dithering at 8 colours: same file size as visually better 64 colours image. Often, dithering is problematic! 8 colours, Diffusion dither 15,9 kB
33. Images Image-class saves picture, independent of the display Variants: Immutable: not modifiable, e.g. when loaded from files, resource bundles or a network.Examples: logos, sprites, … Mutable: modifiable, created by the applicationExamples: off-screen bitmap for double buffering, dynamically modifiable images, images created by the app at runtime for MIDlet file size reasons Andreas Jakl, 2009 33
34. Immutable Images and MIDlets Image file has to be in .jar archive Often, IDEs copy all files of project folders to .jar don’t leave backups or test data in there! Andreas Jakl, 2009 34
35. Image – Example Add an image to the NetBeans-project Create resource folder in the project folder (e.g. /res/) Add folder to the NetBeans-project “Resources” Resource-folder should be included in the packaging process ( project properties) Andreas Jakl, 2009 35 3 1 2
36. Image – Example Load and display the image Andreas Jakl, 2009 36 // Load image as an instance variable // Warning: can take a long time for multiple / large images // -> in that case: asynchronous loading in an own thread! Image titleImg = Image.createImage(“/title.png”);…protected void paint (Graphics g) {g.drawImage(titleImg, 0, 0, Graphics.TOP|Graphics.LEFT);}
37. Mutable Images Created dynamically during runtime Andreas Jakl, 2009 37 classImageDemoCanvasextendsCanvas { privateImagemutableImg; publicImageDemoCanvas () { mutableImg= Image.createImage (10,10); mutableImg.getGraphics().fillArc (0,0,10,10,0,360); } }
38. Conversion Mutable Immutable Mutable Immutable: Immutable Mutable: Andreas Jakl, 2009 38 immutableImg = Image.createImage(mutableImg); Image immutableImg; // theimagetobecopiedimmutableImg = Image.createImage(...); // Create theimmutableimagefrom e.g. a file // Create a mutableimagewiththe same dimensionsImage mutableImg = Image.createImage(immutableImg.getWidth(), immutableImg.getHeight()); // GetthegraphicscontextofthenewmutableimageGraphics g = copy.getGraphics(); // Copytheimmutableimagetothemutableimage (bydrawingit)g.drawImage(immutableImg, 0, 0, TOP|LEFT);