getting the graphics context

to initially (only once) set soe properties like font size etc need to get the graphics context withoud the use of the paint(Graphics g) method.
im used to get that object by calling getGraphics() out of canvas (j2sdk), but this method doesnt exist in j2me.

is there any way to do it ?

Quite simply, you shouldn’t.

Although the Font class does provide factory methods for obtaining font objects, you should steer away from using them as they are buggy as hell on many phones. (For instance, Font objects obtained from the Font factory methods on Samsung phones will return incorrect stringWidths)

Font objects obtained from Graphics contexts are usually correct - therefor the best option is to do lazy initialisation of whatever properties need intialising. (i.e. don’t do the initialisation until the 1st repaint event)

Having said all that, i’m sure there are phones out there that the reverse is true! (but changing lazy init to use static factory methods is dead ezier)

hmmm, im quite not sure if we really point to the same problem, so a little code chunk :


public void paint(Graphics g)
{
      g.setFont(Font.getFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN, Font.SIZE_SMALL));

      renderMenu();
      ....
}

-> dont want that, cause every repaint() the font is set even if its hasnt changed


public MyClass()
{
     Graphics g = myCanvas.getGraphicsFromCosmos();
      g.setFont(Font.getFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN, Font.SIZE_SMALL));

}

public void paint(Graphics g)
{
      renderMenu();
      ....
}

=> mucho better, but not possible …

try to do an image with Image.createImage(width,height), and set/get the font in the graphics context of that image.

oehm … but then i have to use that (useless) image because the graphic context is only attached to this image. i would need to make that image mutable too and … … …
dont think its a too good idea

Setting the font every game loop is what you should be doing !

Obviously, you don’t want to be recreating the Font object every repaint, so simply create it once from the factory method, and store it.


final Font SYSTEM_PLAIN_SMALL = Font.getFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN, Font.SIZE_SMALL);

public void paint(Graphics g)
{
 g.setFont(SYSTEM_PLAIN_SMALL);
 
 renderMenu();
 ....
}

However, as I highlighted in my previous post, relying on the factory methods to obtain your Font objects can be unwise, it potencially makes you code a little more awkward to port to phones that have buggy Font factory methods (many of them do).

Incidentally, your example contains the method renderMenu(), yet I don’t see any parameters passed to it.

A correctly structured program would have a renderMenu() with a signature more like :-

renderMenu(Graphics g, String [] menuOptions, int selectedIndex)

ofcourse, you could abstract further, having a MenuItem [], or even further, delegating the menu rendering to a Menu class, etc etc.
However, for most J2ME games, the simple suggestion above should suffice.

first, the renderMenu() method was shortened by me, indeed it gets the graphics context g as parameter. it does not need more than this.

but im still a little confused about some things.
i dont understand the thing, that im forced to call a method
more often, than i really need too:
if i only need small letters i only need to call setFont() one time (godd position would be constructor). after that, i does not change anymore.
but because i need to modify the graphics context, i have to call it every reapaint() (or test if i have to).

next odd thing is, that i do not understand the technical difference between the factory methods and the font-setter.
why should setFont(SYSTEM_PLAIN_SMALL) work different to getFont(…) ?!

As Abuse says, with Canvas you need to set the font in each call to paint. Check the Javadocs for Canvas’s paint method, and you’ll see that at the start of each call to paint the graphics object’s font is always the default font.

If you can use MIDP 2.0’s GameCanvas instead, then you can just do getGraphics().setFont(…) once. But this isn’t much help unless your target phone supports MIDP 2.0.