Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Java ME - 03 - Low Level Graphics E


Published on

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.


* Canvas
* Key Events
* Game Actions
* Geometry and Text
* Images
* PNG Optimization

Published in: Technology, Education

Java ME - 03 - Low Level Graphics E

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