| Reply | « Previous Thread | Next Thread » |
|
Why are repaint calls ignored in the paint method on the series 40 series? No other phone does this. Anyone know a work around? Attached is a complete midlet that shows the problem. Press the "0" key and you only see one rectangle. Now press the "4" key which only calls repaint again and you see the second rectangel it shoudl have drawn.
Code:
import javax.microedition.lcdui.*;
import javax.microedition.midlet.*;
public class RepaintTest extends MIDlet {
private MainCanvas myCanvas;
private Display myDisplay;
public RepaintTest() {
myCanvas = new MainCanvas();
myDisplay = Display.getDisplay(this);
}
public void startApp()
throws MIDletStateChangeException {
myDisplay.setCurrent(myCanvas);
myCanvas.repaint();
}
public void pauseApp() {}
public void destroyApp(boolean unconditional) {}
class MainCanvas extends Canvas {
public int repainttest3 = 0;
public void paint(Graphics g) {
if(repainttest3==2){
g.setColor(255,0,255);
g.fillRect(45,67,58,23);
repainttest3 = 0;
}
if(repainttest3==1){
g.setColor(0,255,255);
g.fillRect(12,34,58,23);
repainttest3++;
repaint();
}
}
public void keyPressed(int key){
if(key == Canvas.KEY_NUM0){
repainttest3 = 1;
repaint();
}
if(key == Canvas.KEY_NUM4){
repaint();
}
}
}
}
|
| sam.hendley |
| View Public Profile |
| Find all posts by sam.hendley |
|
sam.hendley
Ok, here you are. I even had to run your code trying to solve it, what a shame :) (kidding) There are two things you should know: 1. Repaint requests gather at some System stack and phone does repainting when it has time. Series40 phones are pretty idle with it unfortunately :( If you need to repaint now, use serviceRepaints() method. 2. Repainting itself does not erase previous image. You should paint background color yopurself. After considering this two things, everything works normally :) |
|
You have misunderstood what this demo was supposed to show. I wasnt saying anything about the background repainting or not. What I was trying to show is that the code doent behave in the logical fashion that every other device does. On this device the calls to repaint() from inside paint are ignored. If you try this exact code on other devices you see the two rectangles appear with one button press. If you add a serviceRepaints() call after the repaint() in the painting code it works; *BUT* this doesnt "flush the screen buffer". By "flush the screen buffer" I mean the way that painting commands are not actually sent to the screen until the paint method exits. This is a major problem if you are trying to show a loading screen while loading your graphics and stuff. Here is a slightly modified version of the Main Canvas from below. Try it out, try uncommenting the serviceRepaints(); line and seeing what happens.
Code:
class MainCanvas extends Canvas {
public int repainttest3 = 0;
public void paint(Graphics g) {
if(repainttest3==2){
g.setColor(255,0,255);
g.fillRect(45,67,58,23);
repainttest3 = 0;
}
if(repainttest3==1){
g.setColor(0,255,255);
g.fillRect(12,34,58,23);
repainttest3++;
repaint();
//serviceRepaints();
}
}
public void keyPressed(int key){
if(key == Canvas.KEY_NUM0){
repainttest3 = 1;
repaint();
}
if(key == Canvas.KEY_NUM4){
repaint();
}
if(key == Canvas.KEY_NUM5){
serviceRepaints();
}
}
}
|
| sam.hendley |
| View Public Profile |
| Find all posts by sam.hendley |
|
sam.hendley
Oh, now I see your problem. Why are repaint calls ignored in the paint method on the series 40 series? Don't blame me really hard, I've read this part of docs rather long ago, but as I remeber it's up to phone how to decide when it has time for launching paint(). He also can stack several repaint() request together and call your paint() only once. I guess that Series40 phones clear this stack of painting request after finishing paint() method. If I'm not mistaken this is correct behaviour. Although other phones behave in other way, this also conforms to specifications. This is a major problem if you are trying to show a loading screen while loading your graphics and stuff. Anyone know a work around? 1. I can propose calling serviceRepaints() - this will make repaint() behave similar to wthat you got used to. 2. Otherwise you can load graphics and stuff not inside your paint handler. You may create some variable to count persentage of loaded stuff, increment it step by step and call repaint() after (serviceRepaint() might be also needed). Inside paint() draw animation according to load persentage. Hope this will help :) |
|
Thanks for your input dd. I have come to the same conclusion about the repaint queue being cleared at the end of paint. I think that this is a violation of the MIDP specs though, a call to repaint() should always mean that a call to paint() is going to be made in the future, but there is little point in arguing about it, were stuck with what Nokia gave us. Here is a workaround that works for what I was trying to do, its ugly as anything but it works and it means I don't have to alter the code that works on the other five devices.
Code:
class MainCanvas extends Canvas {
MIDlet midp;
public MainCanvas(MIDlet midp){
this.midp = midp;
}
class forcedRepainter implements Runnable{
public forcedRepainter(){ }
public void run(){
repaint();
}
}
private forcedRepainter fr;
public int repainttest3 = 0;
public void paint(Graphics g) {
if(repainttest3==2){
g.setColor(255,0,255);
g.fillRect(45,67,58,23);
repainttest3 = 0;
}
if(repainttest3==1){
g.setColor(0,255,255);
g.fillRect(12,34,58,23);
repainttest3++;
//repaint();
//serviceRepaints();
fr = new forcedRepainter();
Display.getDisplay(midp).callSerially(fr);
}
}
|
| sam.hendley |
| View Public Profile |
| Find all posts by sam.hendley |
|
repaint() simply marks the entire canvas as dirty and repaint(x,y,w,h) marks the specified region as dirty.
When paint() is called, the internal Graphics clip rectangle will be set to the accumulated dirty region of all previous repaint requests, and the dirty region will be cleared. paint either happens periodically based on a timer, or on demand (by one or more repaint calls), but there is not a one-to-one correspondence between repaint and paint. If a one-one correspondence is desired, use serviceRepaints. |
| Reply | « Previous Thread | Next Thread » |
| Thread Tools | Search this Thread |
|---|---|