views:

2698

answers:

2

What would be the best method for getting a custom element (that is using J2ME native Graphics) painted on LWUIT elements?

The custom element is an implementation from mapping library, that paints it's content (for example Google map) to Graphics object. How would it be possible to paint the result directly on LWUIT elements (at the moment I am trying to paint it on a Component).

Is the only way to write a wrapper in LWUIT package, that would expose the internal implementation of it?

Edit:

John: your solution looks like a lot of engineering :P What I ended up using is following wrapper:

package com.sun.lwuit;

public class ImageWrapper {
  private final Image image;

  public ImageWrapper(final Image lwuitBuffer) {
    this.image = lwuitBuffer;
  }

  public javax.microedition.lcdui.Graphics getGraphics() {
    return image.getGraphics().getGraphics();
  }
}

Now I can get the 'native' Graphics element from LWUIT. Paint on it - effectively painting on LWUIT image. And I can use the image to paint on a component.

And it still looks like a hack :)

But the real problem is 50kB of code overhead, even after obfuscation. But this is a issue for another post :)

/JaanusSiim

A: 

Based on the javadoc for LWUIT and J2ME and guessing that the custom J2ME class is a Canvas it looks like you would have to:

  • Subclass LWUIT's Component class wrapping the custom J2ME component
  • Override the paint() method of the LWUIT Component
  • Subclass the J2ME Graphics class wrapping the LWUIT Graphics class and pass all the method calls through
  • Pass in the wrapped J2ME Graphics implementation to the custom J2ME component's paint method

That third step is an ugly one. Check on the LWUIT mailing list to see if anyone has dome this before. From the published APIs I don't see another way to do it.

Edit: The hack added in the question looks better than my hack for an Image. What I have may be better for a general case, but I don't know either LWUIT or J2ME well enough to really say that.

John Meagher
+1  A: 

I do not think any hacking is necessary. You can subclass the LWTUI Component class and then you can pain whatever you want on to the graphic context of the component. You do not get the native lcdui.Graphics object but an object with a same interface that is easy to use.

If you really need to pass a lcdui.Graphics to some underlying library to display its output then I would suggest this:

Somewhere in your component code (do only when the component contents really need to be changed):

private Image buffer = null; // keep this

int[] bufferArray = new int[desiredWidth * desiredHeight];
javax.microedition.lcdui.Image bufferImage = 
    Image.createEmptyImage(desiredWidth, desiredHeight);
thirPartyComponent.paint(bufferImage.getGraphics());
bufferImage.getRGB(bufferArray,0,1,0,0,desiredWidth, desiredHeight);
bufferImage = null; //no longer needed
buffer = Image.createImage(bufferArray, desiredWidth, desiredHeight);

In the component paint(g) method:

g.drawImage(0,0, buffer);

By doing the hack you did you are losing portablity and also sice you are exposing implementation private object you might also break other things.

Hope this helps.

Honza