02-05-2013 10:30 PM
I have this code:
public class InfoScreen extends MainScreen {
private VerticalFieldManager vfm;
private HorizontalFieldManager hfm;
private CustomTextField tf;
private String info;
public InfoScreen(){
super(NO_VERTICAL_SCROLL | NO_VERTICAL_SCROLLBAR | USE_ALL_HEIGHT | USE_ALL_WIDTH);
vfm = new VerticalFieldManager(NO_VERTICAL_SCROLL | NO_VERTICAL_SCROLLBAR | USE_ALL_HEIGHT | USE_ALL_WIDTH);
vfm.setBackground(BackgroundFactory.createBitmapBa ckground(Bitmap.getBitmapResource("background_vert ical.png")));
//#ifdef GEMINI
tf1= new CustomTextField(220,170);
//#elseif MONZA
tf1 = new CustomTextField(400, 340);
//#endif
info = FileUtil.loadFromResource("info.txt");
tf.setText(info);
Font font = Font.getDefault().derive(Font.PLAIN, 7, Ui.UNITS_pt);
tf.setFont(font);
tf.setBorder(BorderFactory.createBevelBorder(new XYEdges(1, 1, 1, 1)));
EmptyField e;
//#ifdef GEMINI
e = new EmptyField(20, 60);
//#elseif MONZA
ee = new EmptyField(40, 350);
//#endif
hfm = new HorizontalFieldManager();
//#ifdef BB_GEMINI
//hfm.add(new EmptyField(15, 5));
//#endif
hfm.add(new EmptyField(40, 10));
hfm.add(tf);
vfm.add(e);
vfm.add(hfm);
add(vfm);
}
//#ifndef MONZA
protected void sublayout(int width, int height) {
switch (Display.getOrientation()){
case (Display.ORIENTATION_PORTRAIT):
deleteAll();
hfm.deleteAll();
vfm.deleteAll();
hfm.add(new EmptyField(40, 10));
hfm.add(tf);
vfm.add(new EmptyField(40, 350));
vfm.add(hfm);
vfm.setBackground(BackgroundFactory.createBitmapBa ckground(Bitmap.getBitmapResource("background_vert ical.png")));
add(vfm);
break;
case (Display.ORIENTATION_LANDSCAPE):
deleteAll();
vfm.setBackground(BackgroundFactory.createBitmapBa ckground(Bitmap.getBitmapResource("background_hori zontal.png")));
break;
}
super.sublayout(width, height);
}
//#endif
}The purpose of the code is to be able to display the layout correctly boty in landspace and portrait mode.
When I run it on 9870 simulator, I got this:
App Error 104
Uncaught
tackOverflowError
But if hfm.add(tf) is removed from sublayout(), then the code runs fine. No exception triggered at all. Any idea why?
02-06-2013 10:34 AM
Any operation that causes another call to subLayout() will result in a recursive call, which results in another recorsive call, ad naseum.
This results in a stack overflow.
02-06-2013 10:35 AM
inserting, adding and deleting fields to the screen make call to sublayout,
and you add fields inside sublayout so it will call sublayout again and so on you will enter in an infinite loop,
the solution is so simple,
add all you fields in a single manager and overide its sublayout to change the positions and layouts for its childs not to add them again, then add this manager on to the screen,
02-12-2013 11:02 PM
I think I found the cause the error, the CustomTextField class
import net.rim.device.api.ui.Color; import net.rim.device.api.ui.Field; import net.rim.device.api.ui.Font; import net.rim.device.api.ui.Graphics; import net.rim.device.api.ui.Manager; import net.rim.device.api.ui.Ui; import net.rim.device.api.ui.component.TextField; import net.rim.device.api.ui.container.VerticalFieldManager; import net.rim.device.api.ui.decor.BackgroundFactory; public class CustomTextField extends VerticalFieldManager { private int fieldWidth; private int fieldHeight; private TextField textField; public CustomTextField(int width, int height) { super(Manager.NO_VERTICAL_SCROLL); fieldWidth = width; fieldHeight = height; Font fnt = Font.getDefault().derive(Font.PLAIN,6,Ui.UNITS_pt) ; Font fff = Font.getDefault(); VerticalFieldManager vfm = new VerticalFieldManager(Manager.VERTICAL_SCROLL | Manager.VERTICAL_SCROLLBAR); textField = new TextField() { public void paint(Graphics g) { getManager().invalidate(); // g.setGlobalAlpha(150); g.setColor(Color.WHITE); super.paint(g); } }; textField.setEditable(false); vfm.add(textField); add(vfm); } protected void paintBackground(Graphics arg0) { arg0.setGlobalAlpha(200); arg0.setBackgroundColor(Color.BLACK); arg0.clear(); super.paintBackground(arg0); } public void paint(Graphics g) { // draw the border of the text area; int color = g.getColor(); g.setColor(Color.BLACK); // g.drawRect(0, 0, fieldWidth, fieldHeight); g.setColor(color); super.paint(g); } public void sublayout(int width, int height) { if (fieldWidth == 0) { fieldWidth = width; } if (fieldHeight == 0) { fieldHeight = height; } super.sublayout(fieldWidth, fieldHeight); setExtent(fieldWidth,fieldHeight); } public String getText() { return textField.getText(); } public void setText(String text) { textField.setText(text); } }
If its sublayout() method is empty, indeed the application runs smoothly (no crash at all), but the result will be a black vertical field manager (the text it not shown).
02-13-2013 07:11 AM - edited 02-13-2013 07:12 AM
I don't like some of the code you have there, but there is nothing immediately obvious to me. I'm not the best person around and I don't have time to test. But here are some comments and questions
The biggest thing is that I am really not clear what you are trying to do here. It seems you want to set the size of a textField, without actually knowing how much data you are displaying. This seems wrong to me on a number of counts. not least because you probably want this to be flexible based on the font used and the input device's screen size. Can you describe what you are trying to achieve. I think you can probably create something that does the job much more effectively than this will.
Now the question
When this fails, are you specifying a width and height for the CustomTextField?
Now more comments.
You play round with global alpha and color. This means your paint and paintBackground have side effects, if you change these you should change them back. I find the following structure really useful in paint and paintBackground
int currentColor = g.getColor()
int currentGA = g.getGlobalAlpha();
try {
...
super.....
...
} finally {
g.setGlobalAlpha(currentGA);
g.setColor(currentColor);
}
Not sure this will compile, but you get the idea...
Unless you know what you are doing, never call invalidate() from paint or paintBackground - it can be recursive...
So remove this line. Now.
getManager().invalidate();
If this breaks something we should be able to fix it properly.
You have multiple Managers in use here that seem redundant. Why extend VFM and then create a VFM that you add to the VFM you are extending? You should be able to achieve what you want adding a TextField to the CustomTextField (which is a Manager).
In sublayout the height and width passed in are the maximum values you can use. Period. You should always check these. Regardless of width and height you have requested, if your sublayout is passed in a width and height that is less than you want, you will NOT be given extra screen space. So live in the boundaries you have been given.
So this:
super.sublayout(fieldWidth, fieldHeight);
should be
super.sublayout(Math.min(width,fieldWidth(, Math.min(height,fieldHeight));
If you call sublayout, then respect what it gives you. Otherwise you will confuse the processing. You asked it to lay out the fields and set the size it needs, then you should not change this.
There are cases when I do actually change it myself, but I do this on special occasions and only to add space. So again, in this case if you really wanted to set the size, then you could replace this:
setExtent(fieldWidth,fieldHeight);
with
setExtent(Math.max(this.getWidth(),fieldWidth),Mat
ANyway, fix up the issues here, rework your code, and if it is still not resolved, then post back the fixed code and we can investigate again.
02-19-2013 04:50 AM
Sorry for the bad code. I'll fix it ASAP after the top priorites are done.
What I want to achieve is a "sizeable transparent text field", like this.
Being able to be resized is very important, so the layout of the textfield still looks good wether in portrait or landscape orientation.
Initally I was going to put those 3 social media buttons in horizontal allignment, right under the text, but then I changed my mind.