wxGrid or wxGridTableBase loading

If you are using the main C++ distribution of wxWidgets, Feel free to ask any question related to wxWidgets development here. This means questions regarding to C++ and wxWidgets, not compile problems.
Post Reply
kbsimm
Earned a small fee
Earned a small fee
Posts: 10
Joined: Tue Feb 14, 2006 3:46 pm
Location: Seattle
Contact:

wxGrid or wxGridTableBase loading

Post by kbsimm »

I am examing wxGrid to display a table of data. I am looking for a way to load the data to the wxGrid and build the wxGrid based on the data. That is I would put the data in an array[row num][col data] and then create wxGrid(array) similar to JTable in java http://java.sun.com/j2se/1.5.0/docs/api ... Table.html

I have also looked at wxGridTableBase where I would like to do the same thing so I could create wxGrid(wxGridTableBase(array)). Like DefaultTableModel in Java http://java.sun.com/j2se/1.5.0/docs/api ... Model.html

The closest thing I have found is this reference to using a sequence of sequences http://aspn.activestate.com/ASPN/Mail/M ... rd/2985548 albiet they are referring to Python there. That reference does not actually use the sequences?? but rather utilizes wxDBTable. wxDBTable skips the functionality I seek and ties the table directly to the DB.

Other references speak of using wxGridTableBase to load the data but I don't see how wxGridTableBase.SetCellValue is any more efficient than wxGrid.SetValue. I still have to count rows and columns (build functions to do so).

I am concluding that there is no DefaultTableModel equivilant rather wxGridTableBase is equivilant to Java's AbstractTableModel.

So my question is am I correct or have I missed something?
thanks

Brad
phlox81
wxWorld Domination!
wxWorld Domination!
Posts: 1387
Joined: Thu Aug 18, 2005 7:49 pm
Location: Germany
Contact:

Post by phlox81 »

First, C++ is not Java, and wxWidgets not Swing.
wxGrid is a bit of difficult, and its API isn't the userfriendliest.

Depending on what you are doing, I would write my own
wxGridTableBase class, and overwrite the virtual Methods.
Within this class you can do all the Datahandling and so on.
You might take a look at my DataGrid, which connects
a normal DataClass to a wxGrid:
http://forums.wxwidgets.org/viewtopic.php?t=5638

phlox
cpp
I live to help wx-kind
I live to help wx-kind
Posts: 195
Joined: Wed Sep 28, 2005 9:42 pm

Post by cpp »

My 2 cents:
The nice thing about wxWidgets (over Java
Hier Kommt die Sonne...
phlox81
wxWorld Domination!
wxWorld Domination!
Posts: 1387
Joined: Thu Aug 18, 2005 7:49 pm
Location: Germany
Contact:

Post by phlox81 »

cpp wrote: Or, you might consider using wxListView instead, IMHO wxListView is a LOT frendlier, cleaner, and easier to use that wxGrid. (not to mention a lot les buggy). Plus it uses a lot less resources because its native (in Win32 at least).
wxListCtrl/View is only on Windows native, and you get a problem,
if you like to edit the entries after the 1. Column.

wxGridTableBase is a pretty nice class, and easy to derive from.
Especially if you like to edit your entries, this is imho the better way.

phlox
kbsimm
Earned a small fee
Earned a small fee
Posts: 10
Joined: Tue Feb 14, 2006 3:46 pm
Location: Seattle
Contact:

Rebuilding Grid based on TableBase data

Post by kbsimm »

I have created a wxGrid based on a customized wxGridTableBase. Now if I modify the data in wxGridTableBase, That is just change a value but don't add any more data, I can view that updated data by calling wxGrid->ForceRefresh(). But all that does is reread the data for the existing cells. It does not rebuild the wxGrid based on the data.

To give further detail the data in my wxGridTableBase determines the number of rows in my wxGrid. If I add more data theoretically that would result in more rows. I add data to the wxGridTableBase not to the wxGrid. And that is what I want to do...add more data not just change the existing data.

What I need is a way to have the grid rebuilt based on the data in the wxGridTableBase. That is if wxGrid->SetTable(MyGridTableBase) was used to build the grid wxGrid->UpDateTable() is needed to go get the lastest data from the Table Base.

The only method I see for rebuilding the grid is wxGrid::ProcessTableMessage but that requires me to pass a message with details about the rows or columns changed. But in my case the grid doesn't know anything about those rows or columns because they are change in the Table Base.

What I am looking for is some insight into how this was envisioned to work or some direction if I am missing something.
thanks

Brad
timg
Earned some good credits
Earned some good credits
Posts: 148
Joined: Mon Jan 23, 2006 6:52 pm

Post by timg »

For this sort of thing, you need to override the wxGridTableBase. AppendCols an AppendRows functions and then use the wxGrid.AppendCols and AppendRows to add the rows and columns you need.

That way everyone knows what is going on.
kbsimm
Earned a small fee
Earned a small fee
Posts: 10
Joined: Tue Feb 14, 2006 3:46 pm
Location: Seattle
Contact:

Post by kbsimm »

thanks timg...

But appending rows or columns may not be what needs to be done. The model of appending or deleting rows assumes that the user or wxGrid itself is making the decision to add or removed data. I my situation that desicision is made be the data source of the table base.

Assume that I have some function (GetData) that returns to me my data in key value pairs where the key is some id and the value is some object from which I can pull the column data for each row. When I first build the table base (subclass wxGridTableBase) I call my function, sort my data, and place it in some hashmap. GetNumberCols is fixed, GetNumberRows is myHashMap.size(), and I write GetValue to parse the data from the value object for each key. I now have a wxGridTableBase object for wxGrid->SetTable.

After some period of time or after some event the source of the data, which I received by calling my GetData function, has changed the data. So I need to call GetData again and rebuild the wxGridTableBase. The source of the data could be some database, could be some server, could be some instrumentation, or whatever. The point is that wxGrid and wxGridTableBase don't know anything more than the fact that the data has changed. So they can't append or delete rows.

So after further research this morning I have found that it hinges on the takeOwnership argument of SetTable. Setting takeOwnership to true says wxGrid will now own the data. If this is done one would use the methods you speak of to modify data. The caller would wish to own the table base only if the caller where going to modify the base data, as opposed to just a value of the data. Setting takeOwnership to false says that wxGrid will not modify the data (ie add or delete rows) but rather will defer to the table base to manage the data.

If one calls SetTable with takeOwnership set to true then one cannot call SetTable again for the life of the wxGrid unless the whole table base is replaced. There is a check in wxGrid->CreateGrid, wxCheckMsg(...), that I assume will prevent one from calling CreateGrid more then once. A similar effort for SetTable may be necessary. A caller who does not set takeOwnership to true but who attempts to replace the table base with a new table base will find that the old table base is lost.

I believe additional insight can be achieved by studying wxDbTable and wxDbTableBase.
thanks

Brad
phlox81
wxWorld Domination!
wxWorld Domination!
Posts: 1387
Joined: Thu Aug 18, 2005 7:49 pm
Location: Germany
Contact:

Post by phlox81 »

When you Add Rows or the Rows change by an event outside the wxGrid,
you need to send an event to wxGrid, saying how many rows where added / deleted.

Code: Select all

wxGridTableMessage msg( this,wxGRIDTABLE_NOTIFY_ROWS_INSERTED,size-num,num );
GetView()->ProcessTableMessage( msg ); 
phlox
kbsimm
Earned a small fee
Earned a small fee
Posts: 10
Joined: Tue Feb 14, 2006 3:46 pm
Location: Seattle
Contact:

Post by kbsimm »

But that misses the purpose of a model for the grid. Niether the grid nor the grids creator knows that the data changed. Only the model knows. In addition the number of rows in the grid may change depending on the data in the model. Only the model can deterimine how many rows are needed.

And in order for wxGridTableBase to pass a message to wxGrid, wxGrid must be a member of wxGridTableBase which it is presently. And having the wxGrid object as a member of the wxGridTableBase breaks the whole reason to have a seperate class for the model. One might as well just put all the funtionality into wxGrid itelf.

Your method works for Grids that aren't model based but it can't work for model based methods because only the model knows if something changed. (Well it can work and it does because wxGrid is a member of wxGridTableBase but like I said that defeats the purpose of a model for the grid because it's circular.) (Circlular, is that the right term....wxGridTableBase is a member of wxGrid and wxGrid is a member of wxGridTableBase.)
thanks

Brad
phlox81
wxWorld Domination!
wxWorld Domination!
Posts: 1387
Joined: Thu Aug 18, 2005 7:49 pm
Location: Germany
Contact:

Post by phlox81 »

kbsimm wrote:But that misses the purpose of a model for the grid. Niether the grid nor the grids creator knows that the data changed. Only the model knows. In addition the number of rows in the grid may change depending on the data in the model. Only the model can deterimine how many rows are needed.

And in order for wxGridTableBase to pass a message to wxGrid, wxGrid must be a member of wxGridTableBase which it is presently. And having the wxGrid object as a member of the wxGridTableBase breaks the whole reason to have a seperate class for the model. One might as well just put all the funtionality into wxGrid itelf.

Your method works for Grids that aren't model based but it can't work for model based methods because only the model knows if something changed. (Well it can work and it does because wxGrid is a member of wxGridTableBase but like I said that defeats the purpose of a model for the grid because it's circular.) (Circlular, is that the right term....wxGridTableBase is a member of wxGrid and wxGrid is a member of wxGridTableBase.)
but thats the only way...
I know wxGrid isn't perfect, and of course, it should be enough that wxGridTableBase::GetNumberRows/Cols is overloaded, but it isn't.

phlox
kbsimm
Earned a small fee
Earned a small fee
Posts: 10
Joined: Tue Feb 14, 2006 3:46 pm
Location: Seattle
Contact:

Post by kbsimm »

I don't think that is the only way as I noted in my first post this morning. If one calls SetTable with takeOwnership set to false then one can call SetTable again with the same wxGridTableBase. This gives you any updates that have occured to the grids model.
thanks

Brad
Brigand
In need of some credit
In need of some credit
Posts: 6
Joined: Tue Aug 15, 2006 12:23 pm
Location: England

Post by Brigand »

Thanks kbsimm, I had the very same problem and your solution worked for me! :D
Post Reply