Blackberry: Drawing TableModel focus properly - blackberry

I need help with drawing the focus of the selected row properly.
Currently if I select the first item of a category the separatorrow gets highlighted too. So how can I implement my custom focus drawing so that only the selected row gets focused/highlighted?
I am using the posted source code from here: Blackberry Tablemodel gets messed up when scrolling
I am using the Eclipse IDE from RIM and JRE 7.0.0
public class ProductsScreen extends MainScreen
{
private TableModel _tableModel;
private static final int ROW_HEIGHT = 40;
public ProductsScreen(MainCategory mc)
{
super(Manager.NO_VERTICAL_SCROLL | Manager.HORIZONTAL_SCROLL);
DBManager dbman = DBManager.getInstance();
AllProductByCategory[] products = null;
try {
products = dbman.getProducts(mc.getID().intValue());
} catch (DatabaseException e) {
System.out.println(e.getMessage());
e.printStackTrace();
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
setTitle(mc.getName());
_tableModel = new TableModel();//(StringComparator.getInstance(true), 0);
if(products != null)
{
for(int i = 0; i < products.length; i++)
{
ViewableData[] data = products[i].getData().getViewableData();
for(int j = 0; j < data.length; j++)
{
_tableModel.addRow(new Object[] {products[i].getCategoryName(), data[j].getTitle2()});
}
}
}
RegionStyles style = new RegionStyles(BorderFactory.createSimpleBorder(new XYEdges(1, 1, 1, 1), Border.STYLE_SOLID), null, null,
null, RegionStyles.ALIGN_LEFT, RegionStyles.ALIGN_TOP);
TableView tableView = new TableView(_tableModel);
final TableController tableController = new TableController(_tableModel, tableView);
tableController.setFocusPolicy(TableController.ROW_FOCUS);
tableController.setCommand(new Command(new CommandHandler()
{
public void execute(ReadOnlyCommandMetadata metadata, Object context)
{
}
}));
tableView.setController(tableController);
DataTemplate dataTemplate = new DataTemplate(tableView, 2, 2)
{
public Field[] getDataFields(int modelRowIndex)
{
final Object[] data = (Object[]) _tableModel.getRow(modelRowIndex);
Field[] fields = new Field[3];
String rowGroup = (String)data[0];
// we're in a new group if this is the very first row, or if this row's
// data[0] value is different from the last row's data[0] value
boolean isNewGroup = (modelRowIndex == 0) ||
(rowGroup.compareTo((String) ((Object[])_tableModel.getRow(modelRowIndex - 1))[0]) != 0);
if (isNewGroup) {
// make a separator row
fields[0] = new HeaderField((String)data[0],
Field.USE_ALL_WIDTH | Field.NON_FOCUSABLE);
} else {
// this is in the same group as the last product, so don't add anything here
fields[0] = new NullField();
}
// now, add the actual product information
fields[1] = new LabelField((String)data[1],
Field.USE_ALL_WIDTH | Field.FOCUSABLE | Field.USE_ALL_HEIGHT | DrawStyle.ELLIPSIS);
fields[2] = new BitmapField(Bitmap.getBitmapResource("img/bullet_arrow_right.png"));
return fields;
}
};
dataTemplate.createRegion(new XYRect(0, 0, 2, 1)); // group separator (maybe a null field)
dataTemplate.createRegion(new XYRect(0, 1, 1, 1)); // actual rows with product information
dataTemplate.createRegion(new XYRect(1, 1, 1, 1));
dataTemplate.setColumnProperties(0, new TemplateColumnProperties(95, TemplateColumnProperties.PERCENTAGE_WIDTH));
dataTemplate.setColumnProperties(1, new TemplateColumnProperties(5, TemplateColumnProperties.PERCENTAGE_WIDTH));
dataTemplate.setRowProperties(0, new TemplateRowProperties(ROW_HEIGHT)); // separator
dataTemplate.setRowProperties(1, new TemplateRowProperties(ROW_HEIGHT)); // product data
dataTemplate.useFixedHeight(false);
tableView.setDataTemplate(dataTemplate);
add(tableView);
}
}
SOLUTION:
I was able to solve the problem on my own with the following approach.
I just added a overridden LabelField as headerfield and didn't implement its focus drawing. So only the "subfields" get the focus drawn.
Maybe some people would implement it in another way (take a look at the answer from Nate) but it worked for me.

So, I didn't have time to fully integrate your new code sample, which has data model code that I don't have, and which appears to have added a DataTemplate column for a BitmapField. Hopefully, you can adapt what I have to reintegrate those changes.
I'm sure there's more than one way to do this, and I'm not claiming this method to be the highest performance. However, it seems to draw the focus as you would expect, without the separator row getting highlighted when the row directly under it is focused.
What I did was abandon the concept of using multiple regions, and just made my data template 1 row by 1 column. If you want, you can probably make it 1 row by 2 columns, where the column I don't show is the BitmapField.
But, what I did was to place a VerticalFieldManager in the first row in each new group/category. That VerticalFieldManager then contained a separator/header row, a separator field (just a horizontal line), and then the actual product row. If the row was not the first in the group/category, I would just return a simple Field, not a VerticalFieldManager with three Field objects inside it.
Then, I changed the TableController focus policy to FIELD_FOCUS, not ROW_FOCUS. This allows focus to be taken by the VerticalFieldManager, when we're on the first row in a new group/category. However, inside that manager, only the actual product row is focusable. The separator row is not focusable, and will therefore not be drawn with focus.
Here's the code that changed. The rest is the same as in the previous sample I gave you:
_tableController.setFocusPolicy(TableController.FIELD_FOCUS);
_tableView.setController(_tableController);
DataTemplate dataTemplate = new DataTemplate(_tableView, 1, 1) // 1 row now!
{
public Field[] getDataFields(int modelRowIndex)
{
final Object[] data = (Object[]) _tableModel.getRow(modelRowIndex);
String rowGroup = (String)data[0];
// we're in a new group if this is the very first row, or if this row's data[0] value is
// different from the last row's data[0] value
boolean isNewGroup = (modelRowIndex == 0) ||
(rowGroup.compareTo((String) ((Object[])_tableModel.getRow(modelRowIndex - 1))[0]) != 0);
if (isNewGroup) {
LabelField header = new LabelField((String)data[0], Field.USE_ALL_WIDTH | Field.NON_FOCUSABLE);
SeparatorField line = new SeparatorField(Field.USE_ALL_WIDTH) {
public void paint(Graphics g) {
g.setColor(Color.BLACK);
super.paint(g);
}
};
LabelField productRow = new LabelField((String)data[1],
Field.USE_ALL_WIDTH | Field.FOCUSABLE | DrawStyle.HCENTER);
VerticalFieldManager manager = new VerticalFieldManager(Field.USE_ALL_WIDTH | Field.FOCUSABLE |
Manager.NO_VERTICAL_SCROLL | Manager.NO_VERTICAL_SCROLLBAR);
manager.add(header);
manager.add(line);
manager.add(productRow);
return new Field[] { manager };
} else {
return new Field[] { new LabelField((String)data[1],
Field.USE_ALL_WIDTH | Field.FOCUSABLE | DrawStyle.HCENTER) };
}
}
};
// create just one region, with one row and one full-width column
dataTemplate.createRegion(new XYRect(0, 0, 1, 1), _style); // may be a product row, or a product row + separator
dataTemplate.setColumnProperties(0, new TemplateColumnProperties(100, TemplateColumnProperties.PERCENTAGE_WIDTH));
dataTemplate.setRowProperties(0, new TemplateRowProperties(2 * ROW_HEIGHT)); // max height if row + separator
_tableView.setDataTemplate(dataTemplate);
dataTemplate.useFixedHeight(false);
The scrolling is a little funny when you get down to the bottom of the page, but I'm pretty sure I've built VerticalFieldManager subclasses before that acted like lists, that needed some custom scroll handling ... if I get some time tomorrow, I'll try to add that in.
One step at a time, though ...

Related

Set results from math operations into Vaadin Grid in real time (Manually inserting), Using Vaadin 7

The main thing of my problem is, that I want inserting data into my grid from keyboard. Some data are loaded from the database, and user can change (can change the loaded data too) or insert the new data into grid (manually). Then I want have see the results from the columns in last rows (Check the results in my picture) - Results means the number in rows where in the first column is data like - sum, average, min, max ...
So, when I click on the third row, into column e.g Person 3, and when I will change the value from 5 to 6 and in this time the sum will be 16, max will be 6, min 1 and average will be 3.2
My code of Grid is:
Grid grid = new Grid();
IndexedContainer container = new IndexedContainer();
grid.setContainerDataSource(container);
container.addContainerProperty("September", String.class, null);
container.addContainerProperty("Person1", String.class, null);
container.addContainerProperty("Person2", String.class, null);
container.addContainerProperty("Person3", String.class, null);
container.addContainerProperty("Person4", String.class, null);
container.addContainerProperty("Person5", String.class, null);
container.addContainerProperty("Person6", String.class, null);
container.addContainerProperty("Person7", String.class, null);
container.addContainerProperty("Person8", String.class, null);
for(int i = 0; i < 10; i++)
container.addItem(i);
Item item = container.getItem(1);
item.getItemProperty("September").setValue("1.9.2017 Piatok");
item = container.getItem(2);
item.getItemProperty("September").setValue("2.9.2017 Sobota");
....
I tried to add the addValueChangeListener to the grid (container)
container.addValueChangeListener(e -> {
int sum = 0;
for(int i = 0; i < 5; i++)
{
Item item = container.getItem(i);
sum += (Integer) item.getItemProperty("Person3").getValue();
}
item = container.getItem(6);
item.getItemProperty("Person3").setValue(sum);
});
But I get the error message:
sep 15, 2017 4:16:21 PM com.vaadin.server.DefaultErrorHandler doDefault
SEVERE:
com.vaadin.data.Buffered$SourceException
at com.vaadin.ui.AbstractField.setValue(AbstractField.java:546)
at com.vaadin.ui.AbstractField.setValue(AbstractField.java:468)
at com.vaadin.ui.AbstractTextField.changeVariables(AbstractTextField.java:205)
at com.vaadin.server.communication.ServerRpcHandler.changeVariables(ServerRpcHandler.java:616)
at com.vaadin.server.communication.ServerRpcHandler.handleInvocation(ServerRpcHandler.java:463)
at com.vaadin.server.communication.ServerRpcHandler.handleInvocations(ServerRpcHandler.java:406)
at com.vaadin.server.communication.ServerRpcHandler.handleRpc(ServerRpcHandler.java:273)
at com.vaadin.server.communication.UidlRequestHandler.synchronizedHandleRequest(UidlRequestHandler.java:90)
at com.vaadin.server.SynchronizedRequestHandler.handleRequest(SynchronizedRequestHandler.java:41)
at com.vaadin.server.VaadinService.handleRequest(VaadinService.java:1422)
at com.vaadin.server.VaadinServlet.service(VaadinServlet.java:380)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:845)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1689)
at org.eclipse.jetty.websocket.server.WebSocketUpgradeFilter.doFilter(WebSocketUpgradeFilter.java:225)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1676)
at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:581)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143)
at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:548)
at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:226)
at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1174)
at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:511)
at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:185)
at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1106)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:213)
at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:119)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:134)
at org.eclipse.jetty.server.Server.handle(Server.java:524)
at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:319)
at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:253)
at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:273)
at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:95)
at org.eclipse.jetty.io.SelectChannelEndPoint$2.run(SelectChannelEndPoint.java:93)
at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.executeProduceConsume(ExecuteProduceConsume.java:303)
at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.produceConsume(ExecuteProduceConsume.java:148)
at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.run(ExecuteProduceConsume.java:136)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:671)
at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:589)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.StackOverflowError
at java.util.Hashtable.get(Hashtable.java:366)
at com.vaadin.data.util.IndexedContainer$IndexedContainerProperty.setValue(IndexedContainer.java:848)
at my.vaadin.app.MyUI.lambda$11(MyUI.java:3931)
at com.vaadin.data.util.IndexedContainer.firePropertyValueChange(IndexedContainer.java:528)
at com.vaadin.data.util.IndexedContainer.access$1000(IndexedContainer.java:63)
at com.vaadin.data.util.IndexedContainer$IndexedContainerProperty.setValue(IndexedContainer.java:867)
at my.vaadin.app.MyUI.lambda$11(MyUI.java:3931)
Problem is when I try to change 2 and more cells ...
container.addValueChangeListener(e -> {
Item item = container.getItem(6);
if(!e.getProperty().equals(item.getItemProperty("Person3")))
item.getItemProperty("Person3").setValue(54 + "");
if(!e.getProperty().equals(item.getItemProperty("Person4")))
item.getItemProperty("Person4").setValue(65 + "");
});
How I can Fix it ?
This is the problem, I don't want have this footer always visible at the grid. I want see the footers only when I come to the end of the grid. Do you understand that?
This is already answered in Using Vaadin 7.4.9 - How to delete data from the grid
The cause is the same, you are calling container.setValue within the container.addValueChangeListener resulting in an endless loop.
You can NOT CALL item.getItemProperty("Person3").setValue(sum); within the listener.
You have to check if the item you are currently setting is not already set the last time you visited your loop.
Imagine the following:
int otherValue = 10;
public setValue(int newValue) {
int sum = newValue + otherValue; //this is your sum
setValue(sum); //of course this causes a StackOverFlowError
}
Here is a solution that could work for your project:
if(!e.getProperty().equals(item.getItemProperty("Person3"))
item.getItemProperty("Person3").setValue(sum);
Assuming by now you've figured out why you're getting a SOE by using a ValueChangeListener to update the sum row, you can overcome this problem with a similar approach by using an editor CommitHandler, so when the editor changes are saved, the sum row is updated. For the sake of brevity the sample below only calculates the sum, but you can apply similar logic for the rest of your operations:
public class GridWithCalculatedRow extends VerticalLayout {
public GridWithCalculatedRow() {
// indexed container allowing the definition of custom properties
IndexedContainer container = new IndexedContainer();
container.addContainerProperty("September", String.class, null);
container.addContainerProperty("Person1", Integer.class, 0);
container.addContainerProperty("Person2", Integer.class, 0);
container.addContainerProperty("Person3", Integer.class, 0);
// add some dummy data
Random random = new Random();
for (int i = 0; i < 5; i++) {
Item item = container.addItem(i);
item.getItemProperty("September").setValue(String.valueOf(i));
item.getItemProperty("Person1").setValue(random.nextInt(10));
item.getItemProperty("Person2").setValue(random.nextInt(10));
item.getItemProperty("Person3").setValue(random.nextInt(10));
}
Item sumItem = container.addItem(6);
sumItem.getItemProperty("September").setValue("Sum");
// basic grid setup
Grid grid = new Grid();
grid.setContainerDataSource(container);
grid.getColumn("September").setEditable(false);
addComponent(grid);
// initial sum
updateSum(container, sumItem);
// disable editing of sum item
grid.addItemClickListener(event -> {
if (event.getItemId().equals(6)) {
grid.setEditorEnabled(false);
} else {
grid.setEditorEnabled(true);
}
});
// editor commit handler to update the sum
grid.getEditorFieldGroup().addCommitHandler(new FieldGroup.CommitHandler() {
#Override
public void preCommit(FieldGroup.CommitEvent commitEvent) throws FieldGroup.CommitException {
// nothing to do here for now
}
#Override
public void postCommit(FieldGroup.CommitEvent commitEvent) throws FieldGroup.CommitException {
updateSum(container, sumItem);
}
});
}
// recalculate all sums and update the sum item
private void updateSum(IndexedContainer container, Item sumItem) {
Integer person1Sum = 0;
Integer person2Sum = 0;
Integer person3Sum = 0;
// calculate sums
for (int i = 0; i < 5; i++) {
Item item = container.getItem(i);
person1Sum += (Integer) item.getItemProperty("Person1").getValue();
person2Sum += (Integer) item.getItemProperty("Person2").getValue();
person3Sum += (Integer) item.getItemProperty("Person3").getValue();
}
// update grid item
sumItem.getItemProperty("Person1").setValue(person1Sum);
sumItem.getItemProperty("Person2").setValue(person2Sum);
sumItem.getItemProperty("Person3").setValue(person3Sum);
}
}
Result:

Vaadin table | How to set colspan

I'm using vaadin tree table, and I want to set 1st column colspan (equal to the total number of column in table) for some of the rows satisfying some business criteria. For the rest of table rows, individual columns will appear normally.
I've tried using generated columns, and by setting explicit column width, and also by having composite columns; but doing so changes the layout for all the row/columns. Kindly suggest how will we achieve this.
Thanks!
You can set the width of a column by calling TreeTable#setColumnExpandRatio(String columnName, float value).
In the example below, I've set the width of column "Name" to 75%. If you don't specify anything else, the rest of the columns will fit in the rest of the space.
ttable.setColumnExpandRatio("Name", 0.75f);
ttable.setColumnExpandRatio("Number", 0.25f); //not necessary
Try the example below that I modified from Vaadin book:
#Theme("mytheme")
public class MyUI extends UI {
#Override
protected void init(VaadinRequest vaadinRequest) {
final VerticalLayout layout = new VerticalLayout();
layout.setSizeFull();
TreeTable ttable = new TreeTable();
ttable.addContainerProperty("Name", String.class, null);
ttable.addContainerProperty("Number", Integer.class, null);
//Add some sample data
ttable.addItem(new Object[]{"Menu", null}, 0);
ttable.addItem(new Object[]{"Beverages", null}, 1);
ttable.setParent(1, 0);
ttable.addItem(new Object[]{"Foods", null}, 2);
ttable.setParent(2, 0);
ttable.addItem(new Object[]{"Coffee", 23}, 3);
ttable.addItem(new Object[]{"Tea", 42}, 4);
ttable.setParent(3, 1);
ttable.setParent(4, 1);
ttable.addItem(new Object[]{"Bread", 13}, 5);
ttable.addItem(new Object[]{"Cake", 11}, 6);
ttable.setParent(5, 2);
ttable.setParent(6, 2);
ttable.setColumnExpandRatio("Name", 0.75f);
ttable.setColumnExpandRatio("Number", 0.25f);
ttable.setSizeFull();
layout.addComponents(ttable);
layout.setMargin(true);
layout.setSpacing(true);
setContent(layout);
}
#WebServlet(urlPatterns = "/*", name = "MyUIServlet", asyncSupported = true)
#VaadinServletConfiguration(ui = MyUI.class, productionMode = false)
public static class MyUIServlet extends VaadinServlet {
}
}
You can use com.vaadin.ui.Table.setRowGenerator:
Example with Java 8 + Vaadin 7.6.1
setRowGenerator((Table table, Object itemId) -> {
if (itemId instanceof MyClassThatIdentifiesARowToMerge) {
Table.GeneratedRow generatedRow = new Table.GeneratedRow("text-of-merged-cell");
generatedRow.setSpanColumns(true);
return generatedRow; // merge
}
return null; // doesn't merge
} );

Blackberry verticalfieldmanager partial screen scrolling with label fields

I am trying to create a set of FAQ questions and answers using a bunch of LabelFields in a VFM. Issue is that when I try to scroll, it jumps to the bottom of the list and doesn't show the mid-section questions.
public class HelpTab implements ITabAreaLayout, ScrollChangeListener {
public String[] GetQandAs() {
String[] QandAs = new String[22];
QandAs[0] = "Q. ....";
QandAs[1] = "A. ....";
....
....
QandAs[20] = "Q. ...";
QandAs[21] = "A. ....";
return QandAs;
}
VerticalFieldManager _vfm;
public VerticalFieldManager GetLayout() {
_vfm = new VerticalFieldManager(Field.FIELD_LEFT
| Manager.VERTICAL_SCROLL | Manager.VERTICAL_SCROLLBAR);
_vfm.add(UIElements.GetTitleArea(" ? FAQ"));
String[] QandAs = GetQandAs();
for (int i = 0; i < QandAs.length; i++) {
LabelField lblQandA = null;
if ((i % 2) == 0) {
lblQandA = UIElements.GetQuestionLabel(QandAs[i]);
} else {
lblQandA = UIElements.GetAnswerLabel(QandAs[i]);
}
_vfm.add(lblQandA);
}
_vfm.add(new NullField(NullField.FOCUSABLE)); // for scrolling
return _vfm;
}
public void scrollChanged(Manager manager, int newHorizontalScroll,
int newVerticalScroll) {
if (_vfm != null){
_vfm.setVerticalScroll(newVerticalScroll);
}
}
public class HomeScreen extends MainScreen
{
public HomeScreen() {
super(Manager.FIELD_HCENTER | Screen.NO_VERTICAL_SCROLL);
_vfmMain = new VerticalFieldManager();
// add header image
_vfmMain.add(UIElements
.GetBitmapField(UIElements.IMG_HEADER, false));
// add tab strip
_vfmMain.add(MakeTabStrip());
add(_vfmMain);
_vfmTabArea = new HelpTab().GetLayout();
add(_vfmTabArea);
}
}
I was not able to find much help on setVerticalScroll usage, maybe that is the reason for this issue.
Please advise.
Thanks
In your code, you added the focusable null field at the end position of the loop. so if you scroll, it will goto the last element. If you add the focusable field to- After first question, then after second question, ..... so it will scroll one by one.
Try This code -
for (int i = 0; i < QandAs.length; i++) {
LabelField lblQandA = null;
if ((i % 2) == 0) {
lblQandA = UIElements.GetQuestionLabel(QandAs[i]);
} else {
lblQandA = UIElements.GetAnswerLabel(QandAs[i]);
}
_vfm.add(lblQandA);
_vfm.add(new NullField(NullField.FOCUSABLE)); //after each element, add a focusable null field.
}
As Signare has pointed out, the issue here is probably related to your LabelFields not being focusable, which are they are not by default. One answer is to add NullFields as has been suggested. However I suspect you actually want these to be focusable, so the user can click on the one they would like more information on. So make your LabelFields Focusable, by setting the style, for example
LabelField lab = new LabelField("Label", LabelField.FOCUSABLE);
Alternatively, and to my mind preferably, use RichTextField instead of LabelField. This will give you scrolling line by line, LabelField focuses on the whole text.

Not getting the text from Edit Field

In my Application, i am adding a check box, a label field and a Edit Field in a Grid Field manager. Then this grid Field manager, i am adding multiple times in Vertical Field manager. So it is looking like List of items. Now when i checked five check box, i am trying to get the text of the correspondent edit field.
This is the code for Grid Field Manager:
int c[] = {screenWidth/6, (screenWidth)/3, (screenWidth)/2};
gm = new GridFieldManager(c, Manager.VERTICAL_SCROLL);
Logger.out("Grocery", "Here it is coming"+i);
cbfChecked = new CustomCheckBoxField();
cbfChecked.setChangeListener(new FieldChangeListener()
{
public void fieldChanged(Field field, int context)
{
if(checked[i] == false)
{
checked[i] = true;
}
else if(checked[i] == true)
{
checked[i] = false;
Logger.out("Grocery", "It is UnChecked" +checked[i]);
}
}
});
gm.add(cbfChecked);
Logger.out("Grocery", "Adding first Label Field");
LabelFieldCustom lfFrom = new LabelFieldCustom((String) m_vtrItems.elementAt(i),Color.BROWN,FONT_FAMILY_0_SF_AS_16,Field.FIELD_LEFT);
gm.add(lfFrom);
Logger.out("Grocery", "Adding second Label Field");
efcAmount = new EditFieldCustom(Bitmap.getBitmapResource("dob_text_box.png"), 25);
efcAmount.setMargin(new XYEdges(30, 0, 0, 0));
gm.add(efcAmount);
return gm;
Here i am adding the grid field manager multiple times:
for (int i = 0;i < m_vtrItems.size();i++)
{
vfm.add(getRow(i));
vfm.add(new SeparatorField(SeparatorField.NON_FOCUSABLE));
}
Please help me.
I solve the problem. Now i am taking the Edit Field array.

how to set focus on tab till another tab is not selected in blackberry

I am using PaneManagerDemo project code (this project is present in sample demo projects of BB) for developing tab.
I am facing one problem when I select tab it got focus but when I select data below that tab the focus goes to that data.
I want when user select data under tab, it must focus on that data as well as the tab so that user can understand selected data is under which tab.
I am not getting it.
Please tell me.
Here is code for the reference.
public class PaneManagerDemo extends UiApplication
{
public static void main(String[] args)
{
UiApplication app = new PaneManagerDemo();
app.enterEventDispatcher();
}
public PaneManagerDemo()
{
invokeLater(new Runnable()
{
public void run()
{
int headerType = 0;
// Display a dialog for user to select header type
OptionDialog dialog = new OptionDialog();
int result = dialog.doModal();
if(result == Dialog.OK)
{
headerType = dialog.getHeaderType();
}
else if(result == Dialog.CANCEL)
{
System.exit(0);
}
//PaneScreen screen = new PaneScreen(headerType);
PaneScreen screen = new PaneScreen(headerType);
pushScreen(screen);
}
});
}
/**
* A dialog popup used to choose a header type
*/
private static class OptionDialog extends Dialog
{
public static final int SCROLL_HEADER_TYPE = 0;
public static final int TAB_HEADER_TYPE = 1;
private ObjectChoiceField _choiceField;
/**
* Create a new HeaderDialog object
*/
public OptionDialog()
{
super(Dialog.D_OK_CANCEL, "Choose Header Type", Dialog.OK, null, Dialog.GLOBAL_STATUS);
_choiceField = new ObjectChoiceField("", new String[]{"Scrollable", "Tab"}, 0);
add(_choiceField);
_choiceField.setFocus();
}
/**
* Returns an integer representing the header type
*
* #return SCROLL_HEADER_TYPE if scrollable header selected, TAB_HEADER_TYPE if tab header selected
*/
public int getHeaderType()
{
return _choiceField.getSelectedIndex();
}
}
/**
* Main screen for the application. Displays three panes
* switchable via horizontal scroll field or tabs, depending
* on user selection.
*/
private final static class PaneScreen extends MainScreen
{
/**
* Creates a new PaneScreen object
* #param headerType The header type for the PaneManager, scrollable or tab style
*/
public PaneScreen(int headerType)
{
super(Field.FOCUSABLE);
// Instantiate the model for the pane manager and enable looping
PaneManagerModel model = new PaneManagerModel();
model.enableLooping(true);
// Create a pane
VerticalFieldManager vfm = new VerticalFieldManager();
vfm.add(new LabelField("Data 1"));
XYEdges edgesOne = new XYEdges(1, 1, 1, 1);
vfm.setBorder(BorderFactory.createRoundedBorder(edgesOne));
Pane pane = new Pane(new LabelField("Pane 1", Field.FOCUSABLE | Field.FIELD_HCENTER), vfm);
// Add the pane to the model
model.addPane(pane);
// Create a second pane
vfm = new VerticalFieldManager();
for(int i = 0; i < 30; i++)
{
vfm.add(new LabelField("Data " + i, Field.FOCUSABLE));
}
LabelField iconTextLabelField = new LabelField("Pane 2");
model.addPane(new Pane(iconTextLabelField, vfm));
// Create a third pane
vfm = new VerticalFieldManager();
ButtonField button = new ButtonField("Button", ButtonField.CONSUME_CLICK | ButtonField.NEVER_DIRTY);
button.setChangeListener( new FieldChangeListener()
{
public void fieldChanged(Field field, int context)
{
Dialog.inform("Button activated.");
}
});
vfm.add(button);
model.addPane(new Pane(new LabelField("Pane 3"), vfm));
// Choose which pane the model is displaying
model.setCurrentlySelectedIndex(1);
// Create the header and initialize the model and visual properties
TitleView header = null;
PaneManagerController controller = null;
if(headerType == OptionDialog.SCROLL_HEADER_TYPE)
{
header = new HorizontalScrollableTitleView(Field.FOCUSABLE);
controller = new HorizontalScrollableController();
}
else if(headerType == OptionDialog.TAB_HEADER_TYPE)
{
header = new HorizontalTabTitleView(Field.FOCUSABLE);
((HorizontalTabTitleView)header).setNumberOfDisplayedTabs(model.numberOfPanes());
controller = new HorizontalTabController();
}
else
{
throw new IllegalStateException("Header type is not valid.");
}
header.setModel(model);
XYEdges edgesFour = new XYEdges(4, 4, 4, 4);
header.setBorder(BorderFactory.createRoundedBorder(edgesFour));
// Set arrow images
Bitmap leftArrow = Bitmap.getBitmapResource("leftArrow.png");
Bitmap rightArrow = Bitmap.getBitmapResource("rightArrow.png");
if(leftArrow != null)
{
header.setLeftArrow(leftArrow);
}
if(rightArrow != null)
{
header.setRightArrow(rightArrow);
}
// Create the PaneView object, which will display the panes and is
// controlled by the model.
PaneView paneView = new PaneView(Field.FOCUSABLE);
paneView.setBorder(BorderFactory.createSimpleBorder(edgesOne));
paneView.setModel(model);
// Initialize the PaneManagerView
PaneManagerView view = new PaneManagerView(Field.FOCUSABLE, header, paneView);
view.setModel(model);
view.setBorder(BorderFactory.createRoundedBorder(edgesFour));
model.setView(view);
// Initialize the Controller
controller.setModel(model);
controller.setView(view);
model.setController(controller);
view.setController(controller);
add(view);
}
}
}
Only one field in a screen can hold focus at any one time, so you will need to indicate which tab contains the focused field by other means. e.g. by painting the selected tab a different colour.

Resources