Welcome!

Welcome to the official BlackBerry Support Community Forums.

This is your resource to discuss support topics with your peers, and learn from each other.

inside custom component

Java Development

Reply
Developer
Posts: 237
Registered: ‎07-20-2010
My Device: Not Specified
Accepted Solution

ObjectChoiceField not minimizing after change

Hi, I have a simple ObjectChoiceField and it works as expected except it does not disappear after I click on a choide - part of the background work seems to get done but the choices remain visible untill i force a  change in focus, shouldn't the choices minimize after i make a selection?

 

here is my code for the listener:

 

 
    final class  myFieldChangeListener implements FieldChangeListener{
    	ObjectChoiceField myocf;
    	public myFieldChangeListener(ObjectChoiceField ocf){
    		myocf=ocf;
    	}
		public void fieldChanged(Field field, int context) {
			loadMenus(   context, myocf  );
		}
	}
    
    
	private boolean loadMenus( int context, ObjectChoiceField myocf){
		HTTPGetData hgx = new HTTPGetData(orig);
		String menuid = Integer.toString(menuList[myocf.getSelectedIndex()].getValue());
		try {
			hgx.getViaHttpConnection(...);
		} catch (IOException e) {
			System.out.println(e.toString());
		} catch (NullPointerException e){
			System.out.println(e.toString());
			hgx=null;
		}
		if (hgx != null && hgx.toString() != null){
			setGallery(false);
			activeIndex=context;
			buildMenu();
			//innerlower.deleteAll();
			RichTextField datafield = new RichTextField(hgx.toString());
			datafield.setFont(font1);
			
			if (innerlower.getFieldCount()>1){
			try {
 		          innerlower.replace(innerlower.getField(1), 
datafield); }catch(IllegalArgumentException i ) {}
}else{ try { innerlower.add(datafield); }catch(IllegalArgumentException i){} } innerlower.invalidate(); return true; }else return false; } }

 

 

and here is where I make the ObjectChoiceField:

 

else if (menuEntries[context].type.equals("menu") && menuList != null){ // load menu
    HTTPGetData hgx = new HTTPGetData(orig);
    String menuid;
    menuid=Integer.toString(menuList[0].getValue());
    setGallery(false);
    activeIndex=context;
    buildMenu();
    innerlower.deleteAll();
    setGallery(true);
    ObjectChoiceField distance = new ObjectChoiceField("Choose Menu:",menuList);
    distance.setSelectedIndex(0);
    if (menuList.length > 1) {
      distance.setChangeListener(new myFieldChangeListener(distance ));
      innerlower.add( distance);
    }
    if (!loadMenus(context, distance )){ 
	Dialog.alert("Data retrieval error.");
    }
} 

 Why doesn't the ocf automatically minimize (to show only the selected option) after I change the selected option for example from "Pizza" to "Burgers"?   Instead all 5 options remain visible.

 

Developer
Posts: 237
Registered: ‎07-20-2010
My Device: Not Specified

Re: ObjectChoiceField not minimizing after change

I forgot to mention:

I am using jde 5, eclipse plugin 1.1, simulator 9530, winXP Pro v 2002 sp3, jdk 1.6.21.

I no longer have a bb handy to test the code on to see if it's just an issue in the simulator.

Developer
Posts: 1,305
Registered: ‎01-21-2009
My Device: Not Specified

Re: ObjectChoiceField not minimizing after change

I'm guessing that the call to loadMenus involves some networking operations. The way you have written the field change listener, this call is happening on the event thread, causing the display to freeze until the networking operations have finished. Try reorganizing the class so it starts a worker thread that does the blocking operations. After the blocking operations have finished, the worker thread then calls app.invokeLater, passing a Runnable that will update the UI.




Solved? click "Accept as solution". Helpful? give kudos by clicking on the star.
Developer
Posts: 237
Registered: ‎07-20-2010
My Device: Not Specified

Re: ObjectChoiceField not minimizing after change

[ Edited ]

Hi,

Yes there was so I tried like you said and my app started throwing exceptions like crazy, I couldn't catch them either, like other exceptions i've seen in bb they don't behave the same in run and debug mod.

 

So I got rid of  the worker thread and now the exceptions are gone but I'm back to my original problem.

 

Also, when I select an item on the list the item index dreturned by getSelectedIndex is the index before I clicked it, only when I click the ocf a second time do I get the index I want from getSelectedIndex.

Developer
Posts: 1,305
Registered: ‎01-21-2009
My Device: Not Specified

Re: ObjectChoiceField not minimizing after change

Your original problem isn't going to go away until you move the networking code off the event thread. There's absolutely no way around that.

 

Post some code showing how you're trying to implement a worker thread and we can probably help you get it working.

 

As to the inconsistency about the index, I suspect that's a timing issue as well.




Solved? click "Accept as solution". Helpful? give kudos by clicking on the star.
Developer
Posts: 237
Registered: ‎07-20-2010
My Device: Not Specified

Re: ObjectChoiceField not minimizing after change

ok, here is how I did it:

 

 else if (menuEntries[context].type.equals("menu") && menuList != null){ // load menu
//	HTTPGetData hgx = new HTTPGetData(orig);
	String menuid;
	menuid=Integer.toString(menuList[0].getValue());
	setGallery(false);
	activeIndex=context;
	buildMenu();
	innerlower.deleteAll();
	//setGallery(true);
	ObjectChoiceField distance = new ObjectChoiceField("Choose Menu:",menuList);
	distance.setSelectedIndex(0);
	if (menuList.length > 1) {
	//	Dialog.alert("length="+menuList.length);
	//	menuid=Integer.toString(menuList[Dialog.ask("Which menu?",menuList,0)].getValue());
	//	Dialog.alert("menuid="+menuid);
		distance.setChangeListener(new	myFieldChangeListener(distance ));
		distance.setFocusListener(new FocusChangeListener(){
                     public void focusChanged(Field field, int eventType){								// TODO Auto-generated method stub
			if (eventType == FOCUS_LOST){
			  Dialog.alert("focus lost");
			}else if (eventType == FOCUS_GAINED){
			  Dialog.alert("focus gain");
			}
			//innerlower.invalidate();
		}
	});
	try{
		innerlower.add( distance);
		Dialog.alert("added menu ");
	}catch(IllegalStateException i){
		Dialog.alert("ill st ");
	}catch(IllegalArgumentException i){
	        Dialog.alert("ill  arg ");
	}
	}
	try{
		Dialog.alert("ok so far");
		loadMenus(context, distance );
	}catch(IllegalStateException i){
		Dialog.alert("ill st 2 ");
	}catch(IllegalArgumentException i){
		Dialog.alert("ill  arg 2");
	}catch(RuntimeException i){
		Dialog.alert("ill  arg 2");
	}
	//Dialog.alert("Data retrieval error.");
}

 and the loadMenus method:

 

   
private void loadMenus( int context, ObjectChoiceField myocf1){
	final ObjectChoiceField myocf = myocf1;
	// ************ start worker thread
	new Thread(){
		public void run(){
			HTTPGetData hgx = new HTTPGetData(orig);
			String menuid=Integer.toString(menuList[myocf.  getSelectedIndex()].getValue());
			Dialog.alert("menuid="+menuid);
			try {
		         hgx.getViaHttpConnection(orig.getSubDetailsURL() + "?id=" + id + "&menuid=" + menuid+"&city="+TasteMyCity.firstToken(city),true);
			} catch (IOException e) {
				System.out.println(e.toString());
			} catch (NullPointerException e){
				System.out.println(e.toString());
				hgx=null;
			}catch(IllegalStateException i){
				Dialog.alert(" ill state exc xx");
			}catch(RuntimeException i){
				Dialog.alert(" ill state exc zz");
			}
			if (hgx != null && hgx.toString() != null){
				//setGallery(false);
				//activeIndex=context;
				//buildMenu();
				//innerlower.deleteAll();
				final String str =  hgx.toString();
				//innerlower.
				//innerlower.add(datafield);

/// ************ invokeLater ***************** UiApplication.getUiApplication().invokeLater(new Runnable(){ public void run(){ try{ RichTextField datafield = new RichTextField(str); datafield.setFont(font1); if(innerlower.getFieldCount()>1){ //Dialog.alert(" xxx innerlower.getFieldCount="+innerlower.getFieldCount()); try { innerlower.replace(innerlower.getField(1), datafield); }catch(IllegalArgumentException i){ //Dialog.alert(" ill arg exc 1"); }catch(IllegalStateException i){ //Dialog.alert(" ill state exc 1b"); } }else{ // Dialog.alert(" yyy innerlower.getFieldCount="+innerlower.getFieldCount()); try { innerlower.add(datafield); }catch(IllegalArgumentException i){ Dialog.alert(" ill arg exc 2"); }catch(IllegalStateException i){ Dialog.alert(" ill state exc 2b"); } } // myocf.setVisualState(VISUAL_STATE_NORMAL); // myocf.setDirty(true); innerlower.getField(1).setFocus(); //innerlower.setFocus(); innerlower.invalidate(); Dialog.alert(" true"); }catch(IllegalStateException e){ Dialog.alert(" ill state exc 3"); }; } }); //return true; }else { Dialog.alert("Data retrieval error."); //return false; } } }.start(); }

 

 

Thanks in advance.

 

 

Developer
Posts: 1,305
Registered: ‎01-21-2009
My Device: Not Specified

Re: ObjectChoiceField not minimizing after change

Wow, that's complex. I didn't fully analyze it, but one reason for all the exceptions (maybe not the operative one) is that every time you are calling Dialog.alert(), innerlower.add(), and similar methods that affect the UI, you'll get an exception because you're not doing it from the event thread.

 

I'd rather go back to your original code and suggest a simple way to use a worker thread with it. I'd change your field change listener class to this:

 

final class  myFieldChangeListener implements FieldChangeListener{
    public void fieldChanged(Field field, int context) {
        final int choice = ((ObjectChoiceField) field).getSelectedIndex();
        final int ctx = context;
new Thread() { public void run() { loadMenus(ctx, choice); } }.start(); } }

Then modify loadMenus as follows:

 

 

private boolean loadMenus(int context, int choice) {
    HTTPGetData hgx = new HTTPGetData(orig);
    String menuid = Integer.toString(menuList[choice].getValue());
    try {
        hgx.getViaHttpConnection(...);
    } catch (IOException e) {
        System.out.println(e.toString());
    } catch (NullPointerException e) {
        System.out.println(e.toString());
        hgx=null;
    }
    if (hgx != null && hgx.toString() != null) {
        final String hgxString = hgx.toString();
        // do UI updates back on the event thread...
        Runnable updateUI = new Runnable() {
            public void run() {
                setGallery(false);
                activeIndex=context;
                buildMenu();
                //innerlower.deleteAll();
                RichTextField datafield = new RichTextField(hgxString);
                datafield.setFont(font1);

                if (innerlower.getFieldCount() > 1) {
                    try {
                        innerlower.replace(innerlower.getField(1), datafield);
                    } catch(IllegalArgumentException i ) {}
                } else {
                    try {
                        innerlower.add(datafield);
                    } catch(IllegalArgumentException i) {}
                }
                innerlower.invalidate();
            }
        };
        Application.getApplication().invokeLater(updateUI);
        return true;
    } else return false;
}

Not knowing all your code, I may not have correctly isolated all the blocking operations in the worker thread, and I may have left some UI updates in the worker thread, but I hope this gives you the idea.

 

One problem with using a worker thread is letting the user know that something's going on. One way to do this is with a "please wait" screen or dialog. I refer you to a nice three-part article by Peter Strange on how to do this.

Sample "Please Wait" Screen - Part 1

 

Sample "Please Wait" Screen - Part 2

Sample "Please Wait" Screen - Part 3




Solved? click "Accept as solution". Helpful? give kudos by clicking on the star.
Developer
Posts: 237
Registered: ‎07-20-2010
My Device: Not Specified

Re: ObjectChoiceField not minimizing after change

Thanks I'm trying it that way now but get an exception on line

 final int choice = ((ObjectChoiceField) field).getSelectedIndex();

 

ClassCastException: Cannot cast net.rim.device.api.ui.component.ChoiceField$ChangeOptionChoiceField (id=91958272) to net.rim.device.api.ui.component.ObjectChoiceField

 

so I'll try it like this:

 final int choice = ((ChoiceField) field).getSelectedIndex();

 

...

just waiting for the sim to get rolling on the test.....

....

aaaaaannnnddd......

 

Runetimeexception thrown

 

 

 

Developer
Posts: 237
Registered: ‎07-20-2010
My Device: Not Specified

Re: ObjectChoiceField not minimizing after change

maybe something like this:

final int choice = ((ChoiceField.ChangeOptionChoiceField) field).getSelectedIndex();

but of course I cannot resolve ChangeOptionChoiceField since its an inner class.

 

Developer
Posts: 237
Registered: ‎07-20-2010
My Device: Not Specified

Re: ObjectChoiceField not minimizing after change

so I tried again like this:

final ObjectChoiceField distance = new ObjectChoiceField("Choose Menu:",menuList);
        distance.setSelectedIndex(0);
        if (menuList.length > 1) {
	distance.setChangeListener(new	FieldChangeListener( ){
		public void fieldChanged(Field field, int context) {
	        	final int choice =  distance.getSelectedIndex();
		        final int ctx = context;
		        new Thread() {
		                public void run() {
		                    loadMenus(ctx, choice);
		                }
		         }.start();
		}
	});

 but still I get a RunTimeException.