×

Discussion Board

Results 1 to 7 of 7
  1. #1
    Registered User
    Join Date
    Apr 2006
    Posts
    17

    Screen flicker difference between S40 and S60

    Hi -

    I already mumbled a bit about this at http://discussion.forum.nokia.com/fo...d.php?t=123570, but I thought I'd try it with an example. The problem concerns changing screens (canvases) in an app. If I have (like in the code) two screens that are being changed between each other, and being nulled during the change I get an ugly flick on S60 devices (N73 and E51, at least). The same code runs without (at least not as bad) a flick on an S40 device (6131 testing).

    This is a very much simplified case of what's going on in my actual app. The reason I need to null (at least one of) the screen(s) is that I load different images dynamically there, and have to run System.gc() to clear some memory for the new images. Otherwise I wouldn't care to address this problem, but since I haven't come up with any solution to this, I thought I'd ask here. Maybe the code stinks and there's something simple and obvious I haven't thought of (timing things, when to instantiate exactly or smth...) - I'd just like to know if this is just about the code or if it is a S60 specific thing, so I wouldn't waste my time on it more

    Here's an example (modified upon the example at the 1st thread):

    Code:
    import javax.microedition.lcdui.Canvas;
    import javax.microedition.lcdui.Display;
    import javax.microedition.lcdui.Displayable;
    import javax.microedition.lcdui.Graphics;
    import javax.microedition.midlet.MIDlet;
    import javax.microedition.midlet.MIDletStateChangeException;
    
    public class CallTest extends MIDlet {
    
    public static Display display ;
    
    private TestForm1 tf1;
    private TestForm2 tf2;
    
    protected void destroyApp(boolean arg0) throws MIDletStateChangeException {
    
    }
    
    protected void pauseApp() {
    
    }
    
    protected void startApp() throws MIDletStateChangeException {
    	display = Display.getDisplay(this);
    	
    	 tf1 = new TestForm1(this);
    	 tf2 = new TestForm2(this);
    	 display.setCurrent(tf1);
    
    }
    
    public void changeScreen(Object scr) {
    	if(scr instanceof TestForm1){
    		
    		//	comment out the next two lines to remove the flick
    		tf1 = null;	//	Setting the previous screen to null to see the flick
    		tf2 = new TestForm2(this);	//	...and instantiating a new one
    		
    		display.setCurrent(tf2);
    		
    		tf1 = null;	
    		
    	} else {
    
    		//	comment out the next two lines to remove the flick		
    		tf2= null;
    		tf1 = new TestForm1(this);
    		
    		display.setCurrent(tf1);
    	}
    }
    
    
    public class TestForm1 extends Canvas{
    
    	private CallTest ct;
    	
    public TestForm1(CallTest ct){
    	this.ct = ct;
    	this.setFullScreenMode(true);
    }
    protected void paint(Graphics g) {
    
    
    	//fill background with some gray
    	g.setColor(0xaabbaa);
    	g.fillRect(0, 0, this.getWidth(), this.getHeight());
    	
    	g.setColor(0x000000);
    	g.drawString("Some text for scr 1", this.getWidth()/2, this.getHeight()/2, Graphics.HCENTER|Graphics.TOP);
    	
    }
    
    protected void keyPressed(int key){
    	switch ( getGameAction(key) ){
        case Canvas.FIRE:
        	ct.changeScreen(this);
        	break;
    	}
    }
    
    
    }
    
    public class TestForm2 extends Canvas{
    
    	private CallTest ct;
    	
    public TestForm2(CallTest ct){
    	this.ct = ct;
    	this.setFullScreenMode(true);
    }
    protected void paint(Graphics g) {
    
    	//fill background with some gray
    	g.setColor(0xcccccc);
    	g.fillRect(0, 0, this.getWidth(), this.getHeight());
    	
    	g.setColor(0x000000);
    	g.drawString("Other string on scr 2", this.getWidth()/2, this.getHeight()/3, Graphics.HCENTER|Graphics.TOP);
    	
    }
    
    protected void keyPressed(int key){
    	switch ( getGameAction(key) ){
        case Canvas.FIRE:
        	ct.changeScreen(this);
        	break;
    	}
    }
    
    }
    }

  2. #2
    Regular Contributor
    Join Date
    Mar 2003
    Location
    Barcelona, Spain
    Posts
    55

    Re: Screen flicker difference between S40 and S60

    I would do only one class that extends the Canvas and check what to paint inside the paint method:

    Code:
    protected void paint(Graphics g) {
       if(activeScreen == 1) {
          //fill background with some gray
          g.setColor(0xaabbaa);
          g.fillRect(0, 0, this.getWidth(), this.getHeight());
    	
          g.setColor(0x000000);
          g.drawString("Some text for scr 1", this.getWidth()/2, this.getHeight()/2, Graphics.HCENTER|Graphics.TOP);
       } else {
         //fill background with some gray
         g.setColor(0xcccccc);
         g.fillRect(0, 0, this.getWidth(), this.getHeight());
    	
         g.setColor(0x000000);
         g.drawString("Other string on scr 2", this.getWidth()/2, this.getHeight()/3, Graphics.HCENTER|Graphics.TOP);
       }
    }
    And then change the 'activeScreen' value in the changeScreen method. After changing the value, clearing the previous resources and allocating the new ones you should call repaint() and serviceRepaints().

  3. #3
    Registered User
    Join Date
    Apr 2006
    Posts
    17

    Re: Screen flicker difference between S40 and S60

    Cheers, rrafols for the reply. Having only one canvas helps with this issue, definitely.

    The problem though, that I'm having is a classic one - the app I'm working on has been developed on S40, then later moved to support S60 too. And surprise - there's all these little differences. Right now there's around 10 different screens (each as its own class), and it looks like I'm better off rewriting a whole bunch of it at a suitable time (another classic ).

  4. #4
    Regular Contributor
    Join Date
    Mar 2003
    Location
    Barcelona, Spain
    Posts
    55

    Re: Screen flicker difference between S40 and S60

    This is only a quick idea but it might work.

    Instead of extending from Canvas, you could change these classes to implement an interface.

    In the interface you should put all the Canvas methods you need (paint, keyPressed, keyReleased...)


    Code:
    public class TestForm1 implements Paintable {
    ...
       public void paint(Graphics g) {
       ...
       }
    ...
    }
    
    public class TestForm2 implements Paintable {
    ...
       public void paint(Graphics g) {
       ...
       }
    ...
    }
    
    public interface Paintable {
       public void paint(Graphics g);
    }
    Then you should create a class that extends from Canvas and then manage there all the logic of the painting.

    Code:
    public class AppCanvas extends Canvas {
       private Paintable currentScreen;
    
       public void paint(Graphics g) {
          if(currentScreen != null) {
             currentScreen.paint(g);
          }
        }
    
       public void setCurrentScreen(Paintable p) {
          currentScreen = p;
       }
    }
    Obviously you would have to change all calls to Display.setCurrent(..) for a call for setCurrentScreen of this class.

    Hope this saves you some time of rewriting

  5. #5
    Registered User
    Join Date
    Apr 2006
    Posts
    17

    Re: Screen flicker difference between S40 and S60

    Cheers again, I'll definitely consider this, nice pattern thinking. I (only) guess that the S60 side flick probably benefits from this, having one Graphics instance instead of changing it all the time for different canvases like before, no matter what resources I'm nulling or not.

    This might be a case-by-case thing, but would you throw a wild guess (or even facts) on the efficiency of using only one canvas instead of multiple screens (having their "own" canvases)? Any major difference? Or rather having effect on e.g. maybe having the codebase more organized? I wonder how the UI frameworks have this solved - better go see some source stuff before implementing on my own.

  6. #6
    Regular Contributor
    Join Date
    Mar 2003
    Location
    Barcelona, Spain
    Posts
    55

    Re: Screen flicker difference between S40 and S60

    Check this url:
    http://blogs.s60.com/java/2007/11/ne...3rd_ed_fp.html

    New Java features of 3rd Ed. fp 2

    [...]

    One smaller, but rather dramatic change has been implemented on LCDUI Canvas class. Previously each Canvas instance contained it's own double buffer for graphics contents. The size of the buffer image is the size of the screen so it consumes quite much runtime memory. Double buffering for Canvas is nowadays required feature by MIDP specification 2.1. If a MIDlet has multiple Canvas instances the memory may easily run out. On other platforms e.g. Nokia Series 40 had implemented different double buffering scheme: each Canvas instance simply shared the same double buffer. We at S60 Java decided to implement the same scheme and as a result we are behaving the same with Series 40 devices.
    So in previous S60 editions it would be more efficient to have only 1 Canvas.

  7. #7
    Registered User
    Join Date
    Apr 2006
    Posts
    17

    Re: Screen flicker difference between S40 and S60

    Cool - this was exactly what I was after, interesting to find out about how the double buffering has been implemented - the sharing part on S40 - I guess that's been a clever move from them..

Similar Threads

  1. S40 - S60 Calling sequence diff
    By prakash.raman in forum Mobile Java General
    Replies: 1
    Last Post: 2008-07-23, 11:07
  2. Basic difference between S40. S60, and S80
    By ashishgavande in forum Mobile Java General
    Replies: 2
    Last Post: 2007-11-21, 08:10
  3. What is going on with Vibration on S60?
    By amd_rikus in forum Mobile Java General
    Replies: 3
    Last Post: 2006-06-16, 00:29
  4. Nokia手机主要参数列表
    By cqucyf in forum [Archived] Other Programming Discussion 关于其他编程技术的讨论
    Replies: 0
    Last Post: 2005-05-04, 16:34

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
×