A typical LWUIT application is essentially composed of 3 layers (this is a gross simplification though), the bg painters are responsible for drawing the background of all components including the main form. The component draws its own content which might overrule the painter and the glass pane paints last...
Essentially the glass pane is a painter that allows us to draw an overlay on top of the LWUIT application. Initially we didn't think we need a glass pane, we used to suggest that people should override the form's paint() method to reach the same result. Feel free to try and guess why this failed before reading the explanation in the next paragraph.
Overriding the paint method of a form worked initially, when you enter a form this behaves just as you would expect. However, when modifying an element within the form only that element gets repainted not the entire form! So if I had a form with a Button and text drawn on top using the Form's paint method it would get erased whenever the button got focus.
Thats good for the forms paint method, calling the forms paint method would be REALLY expensive for every little thing that occurs in LWUIT. However, we do want overlays for some things and we don't need to repaint every component in the screen to get them. The glass pane is called whenever a component gets painted, it only paints within the clipping region of the component hence it won't break the rest of the glass pane.
The painter chain is a tool that allows us to chain several painters together to perform different logistical tasks such as a validation painter coupled with a fade out painter. The sample bellow shows a crude validation panel that allows us to draw error icons next to components while exceeding their physical bounds as is common in many user interfaces
public class ValidationPane implements Painter {
private Vector components = new Vector();
private static Image error;
public ValidationPane(Form parentForm) {
try {
if(error == null) {
error = Image.createImage("/error.png");
}
} catch (IOException ex) {
ex.printStackTrace();
}
PainterChain.installGlassPane(parentForm, this);
}
public void paint(Graphics g, Rectangle rect) {
for(int iter = 0 ; iter < components.size() ; iter++) {
Component c = (Component) components.elementAt(iter);
if(c == null) {
components.removeElementAt(iter);
continue;
}
Object p = c.getClientProperty(VALIDATION_PROP);
int x = c.getAbsoluteX();
int y = c.getAbsoluteY();
x -= error.getWidth() / 2;
y += c.getHeight() - error.getHeight() / 2;
g.drawImage(error, x, y);
}
}
public void addInvalid(Component c) {
components.addElement(c);
}
public void removeInvalid(Component c) {
components.removeElement(c);
}
}
0 comments:
Post a Comment