com.codename1.ui.table.Table scroll behaviour issue

18 views
Skip to first unread message

shop.servic...@gmail.com

unread,
Jan 23, 2019, 7:41:40 PM1/23/19
to CodenameOne Discussions
If you are experiencing an issue please mention the full platform your issue applies to:
IDE: NetBeans/Eclipse/IDEA
Desktop OS
Simulator
Device PC, Android, IOS

Sorry for the Table Population Hack,

I am expecting to edit column 0 and when I click/Press on a row that exists within the non scrolled region all is well.
Scroll down then click/press a cell to edit (casted as TextField) and the Table scrolls back to top.
As soon as The Table scrolls back to top, the cell I pressed and was going to edit, looses focus and of course would execute an actionEvent (Not Shown Here)

How do I prevent the scrolling back to top when I press a cell in this case?

Thanks In Advance!


            Form hi = new Form("Table", new BorderLayout());
            hi.setScrollableY(true);
            Container header = new Container(new BoxLayout(BoxLayout.Y_AXIS));
            TableModel modelHeader = new DefaultTableModel(new String[]{"Complaint", "Hours", "Dollars"}, new Object[][]{
                
                
                ,}) {
                public boolean isCellEditable(int row, int col) {
                    return col != 0;
                }
            };
            Table table1 = new Table(modelHeader) {
                @Override
                protected TableLayout.Constraint createCellConstraint(Object value, int row, int column) {
                    TableLayout.Constraint con = super.createCellConstraint(value, row, column);
                    if (row == 1 && column == 1) {
                        con.setHorizontalSpan(2);
                    }
                    con.setWidthPercentage(33);
                    return con;
                }
            };
            header.addComponent(table1);
            int RowNum = 1;
            TableModel model = new DefaultTableModel(new String[]{"", "", ""}, new Object[][]{
                {"Row " + (RowNum++), "Row A", "Row X"},
                {"Row " + (RowNum++), "Row A", "Row X"},
                {"Row " + (RowNum++), "Row A", "Row X"},
                {"Row " + (RowNum++), "Row A", "Row X"},
                {"Row " + (RowNum++), "Row A", "Row X"},
                {"Row " + (RowNum++), "Row A", "Row X"},
                {"Row " + (RowNum++), "Row A", "Row X"},
                {"Row " + (RowNum++), "Row A", "Row X"},
                {"Row " + (RowNum++), "Row A", "Row X"},
                {"Row " + (RowNum++), "Row A", "Row X"},
                {"Row " + (RowNum++), "Row A", "Row X"},
                {"Row " + (RowNum++), "Row A", "Row X"},
                {"Row " + (RowNum++), "Row A", "Row X"},
                {"Row " + (RowNum++), "Row A", "Row X"},
                {"Row " + (RowNum++), "Row A", "Row X"},
                {"Row " + (RowNum++), "Row A", "Row X"},
                {"Row " + (RowNum++), "Row A", "Row X"},
                {"Row " + (RowNum++), "Row A", "Row X"},
                {"Row " + (RowNum++), "Row A", "Row X"},
                {"Row " + (RowNum++), "Row A", "Row X"},
                {"Row " + (RowNum++), "Row A", "Row X"},
                {"Row " + (RowNum++), "Row A", "Row X"},
                {"Row " + (RowNum++), "Row A", "Row X"},
                {"Row " + (RowNum++), "Row A", "Row X"},
                {"Row " + (RowNum++), "Row A", "Row X"},
                {"Row " + (RowNum++), "Row A", "Row X"},
                {"Row " + (RowNum++), "Row A", "Row X"},
                {"Row " + (RowNum++), "Row A", "Row X"},
                {"Row " + (RowNum++), "Row A", "Row X"},
                {"Row " + (RowNum++), "Row A", "Row X"},
                {"Row " + (RowNum++), "Row A", "Row X"},
                {"Row " + (RowNum++), "Row A", "Row X"},
                {"Row " + (RowNum++), "Row A", "Row X"},
                {"Row " + (RowNum++), "Row A", "Row X"},
                {"Row " + (RowNum++), "Row A", "Row X"},
                {"Row " + (RowNum++), "Row A", "Row X"},
                {"Row " + (RowNum++), "Row A", "Row X"},
                {"Row " + (RowNum++), "Row A", "Row X"},
                {"Row " + (RowNum++), "Row A", "Row X"},
                {"Row " + (RowNum++), "Row A", "Row X"},
                {"Row " + (RowNum++), "Row A", "Row X"},
                {"Row " + (RowNum++), "Row A", "Row X"},
                {"Row " + (RowNum++), "Row A", "Row X"},
                {"Row " + (RowNum++), "Row A", "Row X"},
                {"Row " + (RowNum++), "Row A", "Row X"},
                {"Row " + (RowNum++), "Row A", "Row X"},
                {"Row " + (RowNum++), "Row A", "Row X"},
                {"Row " + (RowNum++), "Row A", "Row X"},
                {"Row " + (RowNum++), "Row A", "Row X"},
                {"Row " + (RowNum++), "Row A", "Row X"},
                {"Row " + (RowNum++), "Row A", "Row X"},
                {"Row " + (RowNum++), "Row A", "Row X"},
                {"Row " + (RowNum++), "Row A", "Row X"},
                {"Row " + (RowNum++), "Row A", "Row X"},
                {"Row " + (RowNum++), "Row A", "Row X"},
                {"Row " + (RowNum++), "Row A", "Row X"},
                {"Row " + (RowNum++), "Row A", "Row X"},
                {"Row " + (RowNum++), "Row A", "Row X"},
                {"Row " + (RowNum++), "Row A", "Row X"},
                {"Row " + (RowNum++), "Row A", "Row X"},
                {"Row " + (RowNum++), "Row A", "Row X"},
                {"Row " + (RowNum++), "Row A", "Row X"},
                {"Row 2", "Row B can now stretch", null},
                {"Row 3", "Row C", "Row Z"},
                {"Row 4", "Row D", "Row K"},}) {
                public boolean isCellEditable(int row, int col) {
                    if (col == 0) {
                        return true;
                    } else {
                        return false;
                    }
                }
            };
            Table table = new Table(model) {
                private int selectedRow = -1;
                @Override
                protected Component createCell(Object value, int row, int column, boolean editable) {
                    Component cell;
                    if (row < 0) {
                        cell = super.createCell(value, row, column, editable);
                    } else {
                        if (column == 0) {
                            cell = new TextField(value.toString());
                            ((TextField) cell).addPointerReleasedListener(e -> {
                                selectedRow = row;
                                setModel(getModel());
                            });
                        } else {
                            cell = new Button(value.toString());
                            cell.setUIID("TableCell");
                            ((Button) cell).addPointerReleasedListener(e -> {
                                selectedRow = row;
                                setModel(getModel());
                            });
                        }
                    }
                    if (selectedRow > -1 && selectedRow == row) {
                        cell.getAllStyles().setBgColor(0xff0000);
                        cell.getAllStyles().setBgTransparency(100);
                    }
                    return cell;
                }
                @Override
                protected TableLayout.Constraint createCellConstraint(Object value, int row, int column) {
                    TableLayout.Constraint con = super.createCellConstraint(value, row, column);
                    if (row == 1 && column == 1) {
                        con.setHorizontalSpan(5);
                    }
                    con.setWidthPercentage(33);
                    return con;
                }
            };
            hi.add(BorderLayout.NORTH, header);
            table.setScrollableY(true);
            hi.add(BorderLayout.CENTER, table);
            hi.show();

Shai Almog

unread,
Jan 23, 2019, 10:24:36 PM1/23/19
to CodenameOne Discussions
You have nested scrollables here. The table and its parent container are both scrollable and this causes confusion. Ideally it should cause an error but these things are hard to detect efficiently in the code and you get "weird" failures like that.

I would suggest using a non-scrollable border layout and letting the table do the scrolling.

shop.servic...@gmail.com

unread,
Jan 24, 2019, 8:18:59 AM1/24/19
to CodenameOne Discussions
Sorry, An Oversight from a cut and paste.

hi.setScrollableY(false);

With only Table table.setScrollableY(true); being scrollable,
swipe down to the bottom and tap the Row 2 or 3 or 4 cells and you will see the table scrolls to the top every time.

Regards.

Shai Almog

unread,
Jan 24, 2019, 10:31:02 PM1/24/19
to CodenameOne Discussions
It's because you invoke setModel() which causes the table to effectively rebuild from scratch. You should instead update the cell/row not rebuild the entire table.

shop.servic...@gmail.com

unread,
Jan 25, 2019, 9:04:39 AM1/25/19
to CodenameOne Discussions
This method was taken from your answer to how to highlight a selected row.

Ultimate goal is to efficiently highlight a selected row

Regards.

shop.servic...@gmail.com

unread,
Jan 25, 2019, 9:56:54 AM1/25/19
to CodenameOne Discussions
Attached is the requirement example I have in rendering a Table

Table contains one of n Estimate Groups, The 2 highlighted rows in the attachment are a summary of the Parts / Labor that make up a Group

When we click on a column, we highlight only that column, however when we make changes to the table such as add a new group or group entry, we have to render the table to highlight the changes in the Group summaries as shown in the attached image.

Regards.
RoEstimatesRendering_01-25-2019.JPG

Shai Almog

unread,
Jan 26, 2019, 12:41:25 AM1/26/19
to CodenameOne Discussions
That was a mistake. I didn't see it in the test case since there was no scrolling. I guess the fix would be to keep a single listener for the entire row and update the selected state on the component.
E.g.

Map<Integer, ActionListener> rowListeners;


Then bind the listener for a specific row or create it. This solution will also need to keep the currently selected components so we can remove the selection from them. It's a bit of a hassle so it's not something I can whip up quickly right now.

shop.servic...@gmail.com

unread,
Jan 26, 2019, 8:05:11 AM1/26/19
to CodenameOne Discussions
I can appreciate that.

com.codename1.ui.table.Table is very useful to us as we use JTables in Swing frequently.
Our product suite is based in pure java RMI server / clients Swing GUI's and many classes are ported to mobile devices.
We have accomplished much on the Swing side, it's very cost effective not to have to reinvent the wheel.

Are there any other codename1 alternatives that provide features like renderers and row highlighting inherent in Swing?

Regards

shop.servic...@gmail.com

unread,
Jan 26, 2019, 4:10:59 PM1/26/19
to CodenameOne Discussions
The more I work with the com.codename1.ui.table.Table and add complexities, the more it frustrates me.

Is there a better solution in codename1 dealing with tables that are renderable and feature rich?

Regards

Shai Almog

unread,
Jan 26, 2019, 11:17:10 PM1/26/19
to CodenameOne Discussions
JTable is pretty frustrating too... Unlike table you have more state than the renderers/editors mess.
You can use the TableLayout directly if you prefer.
I think this is pretty doable in table with the current feature set I just don't have the time right now to do that.

shop.servic...@gmail.com

unread,
Jan 27, 2019, 8:02:31 AM1/27/19
to CodenameOne Discussions
Thanks, I'm not pushing you to make any changes more over just to make sure I am not overlooking another package that may exist that will be more feature rich.
I appreciate your support and do not want to jeopardize same.

From what I have read, the TableLayout class is fixed in size and can not be altered (add/delete rows dynamically) like Table can.

If this is the case, I think it best for us to continue to work with Table.

Thanks for all your support.

Regards.

Shai Almog

unread,
Jan 27, 2019, 10:15:51 PM1/27/19
to CodenameOne Discussions
Table is written on top of Table layout, you can just recreate the layout and apply it again.

FYI you can debug directly into the Codename One sources to get insight into how things work. This post is a bit old but most of this still works as is: https://www.codenameone.com/blog/how-to-use-the-codename-one-sources.html
Reply all
Reply to author
Forward
0 new messages