Jump to content


Photo

NextGrid6 string processing, NextVirtualGrid6 and a few questions and bugs


  • Please log in to reply
45 replies to this topic

#1 karl

karl
  • Members
  • 52 posts
  • Gender:Male
  • Location:Austria

Posted 30 November 2015 - 04:52 PM

Hi Boki,

 

I recently tried using your NextGrid6 component with some large datastructure containing  6 cols with a lot of very long strings

and over 3 000 Rows (the grid consists of TextColums only).

But I figured that it was quite slow compared to the standard Vcl-StringGrid.

Where populating the Vcl-StringGrid (with the exact same data) happend without any noticable delay,

when populating NextGrid6 the application froze for about 2 seconds (I used BeginUpdate; EndUpdate and AddRow(3 000)- all Rows at once, like you suggest in the documentation).

 

I'm guessing this is becouse you use WideString for all internal string processing.

Vcl-StringGrid uses the default String type which is UnicodeString (in Delphi Versions starting with Delphi 2010 I think).

Using UnicodeString is much faster then using WideString becouse it uses reference counting with copy on write.

WideString uses copy by value. (see http://docwiki.embar..._Types_(Delphi) )

 

You probably use WideString becouse of compatability to older Versions of Delphi, but it would be really

nice to have your components use UnicodeString (just string) for newer Versions ;) .

 

 

 

To circumvent this speed issue I now use NextVirtualGrid6, but I ran into some questions and bugs:

 

1) I don't know how to make the grid reload it's data, for example when i change the data of my data-structure which gets queried in the getCell-Event.

    I tried              NextVirtualGrid61.DataChanged;            but nothing happens.

 

2) There is an OnCulumnHeaderClick event, but it seems to never get called when i click on a ColumnHeader, maybe there is a bug?

 

3) If I pull the NextVirtualGrid6 and NextCellSource components on my Form their units are not automatically added to the uses list

   (not really a big deal, but I wanted to point it out to you)

 

4) I noticed that NextVirtualGrid6 has some procedures for sorting. How do they work and how do I use them?

 

5) Feature Request: It would be nice to have an AfterCellSetEvent. I would like to call bestFitCol() in that event.

 

6) Also It would be nice to have an OnColumnHeaderClick-Event with a (aCol: Integer) parameter, let me illustrate that with some code:

 

   Now if I want to assign the OnHeaderClick event with eg some custom sorting for the column I clicked,

   I would have to assign an event for every column to implement some custom behavior for clicks on different columns:

 

                                                                                                         Column1.OnHeaderClick := OnHeaderClick1;

                                                                                                         Column2.OnHeaderClick := OnHeaderClick2;                      and so on..

 

What I would like to do instead is this:

                                  

interface

   procedure FormCreate;

   procedure OnHeaderClick(aCol: integer);

 

implemementation

 

procedure OnHeaderClick(aCol: integer);

begin

  doSomeCustomStuffWithClickedColumn(aCol);

end;

 

procedure FormCreate;

begin

  Column1.OnHeaderClick := OnHeaderClick;

  Column2.OnHeaderClick := OnHeaderClick;

end;                                                               

 

 

I added a tiny sample project for better understanding of my obove points.

Attached File  VirtualGrid_Sample.zip   53.82KB   5 downloads



#2 Boki (Berg)

Boki (Berg)

    Boki (Berg)

  • Forum Admin
  • PipPipPipPipPip
  • 8,191 posts
  • Gender:Male

Posted 30 November 2015 - 05:21 PM

Hi Karl,

 

Thank I will work on it today.

 

If you want, you can send me non-virtual demo too. Most probably some switch is causing refreshing after every update which I need to fix. I hope that soon I will exit this early bugs.


boki@bergsoft.net | LinkedIn Profile
--
BergSoft Home Page: www.bergsoft.net
Users Section: users.bergsoft.net
Articles and Tutorials: help.bergsoft.net (Developers Network)
--
BergSoft Facebook page
--
Send us applications made with our components and we will submit them on: www.bergsoft.net/apps.htm. Link to this page will be also set on home page too.

#3 Boki (Berg)

Boki (Berg)

    Boki (Berg)

  • Forum Admin
  • PipPipPipPipPip
  • 8,191 posts
  • Gender:Male

Posted 30 November 2015 - 06:44 PM

Hi,

 

Couple of answers, more as soon I investigate one by one:

 

1) This method update scrollbars and repaint. For example if at one moment you have much more data and scrollbar must appear.

 

2) My apologise :( , I don't see where is this event. Maybe you saw OnHeaderButtonClick event of Column? If there isn't I will add it.

 

3) I think that they are added (standard feature by IDE) when you hit Run.

 

4) You can use OnAfterSort for example and then sort your data as Grid only virtually manage it. If you set Sorted for Column, this event will again be called and same code will be executed.

 

5) Maybe something like OnCellValueChanged?

 

PS. NextGrid6 inherits VirtualNextGrid and I simply add my own data management system beneath surface.


boki@bergsoft.net | LinkedIn Profile
--
BergSoft Home Page: www.bergsoft.net
Users Section: users.bergsoft.net
Articles and Tutorials: help.bergsoft.net (Developers Network)
--
BergSoft Facebook page
--
Send us applications made with our components and we will submit them on: www.bergsoft.net/apps.htm. Link to this page will be also set on home page too.

#4 karl

karl
  • Members
  • 52 posts
  • Gender:Male
  • Location:Austria

Posted 30 November 2015 - 08:11 PM

Hi Boki, thank you for your prompt answers,

 

1) Ok, but is there a method to notify the grid that the data-structure (in my example the 2 dimensional array) is changed, so that all cells will be requeried ? (in other words repopulate the entire grid with the changed data-structure)

 

2)  Yes. I mean OnHeaderButtonClick, it is there but it just doesn't get called.

 

3) Sorry, my fault. You're right.

 

4) I don't think I understand 100%. When is this onAfterSort event called?

 

5) Yes, that sounds good.



#5 Boki (Berg)

Boki (Berg)

    Boki (Berg)

  • Forum Admin
  • PipPipPipPipPip
  • 8,191 posts
  • Gender:Male

Posted 30 November 2015 - 09:39 PM

Hi Karl,

 

1) You notify grid to update scrollbars when your data structure is changed in some way. VirtualGrid is never populated with your data, it only displays data that is on screen, and in number of rows you set in VirtualCellSource. So, you call DataChanged and he update ScrollBars. This is not time expensive operation.

 

2) I will add OnHeaderClick event too. This OnHeaderButtonClick is for different purpose.

 

4) OnAfterSort is called after user click on header to sort grid. Now you have a chance to sort your structure (or switch indexes and similar). VirtualNextGrid is only a window to your data.


boki@bergsoft.net | LinkedIn Profile
--
BergSoft Home Page: www.bergsoft.net
Users Section: users.bergsoft.net
Articles and Tutorials: help.bergsoft.net (Developers Network)
--
BergSoft Facebook page
--
Send us applications made with our components and we will submit them on: www.bergsoft.net/apps.htm. Link to this page will be also set on home page too.

#6 karl

karl
  • Members
  • 52 posts
  • Gender:Male
  • Location:Austria

Posted 30 November 2015 - 09:48 PM

Hi Boki,

 

1) Yes, I understand that, maybe I didn't explain well what i wanted to do :). I figured it out though.   

     This is what I was looking for, requeries the data in case my data-structure is changed.

 

with NextVirtualGrid61 do
    for r := 0 to RowCount-1 do
      RefreshRow( r );

 

2) Thank you.

 

3) Ok, then OnAfterSort was what I was looking for.



#7 karl

karl
  • Members
  • 52 posts
  • Gender:Male
  • Location:Austria

Posted 30 November 2015 - 10:03 PM

3) But how do I obtain which column was clicked in the OnAfterSort- Event ?



#8 Boki (Berg)

Boki (Berg)

    Boki (Berg)

  • Forum Admin
  • PipPipPipPipPip
  • 8,191 posts
  • Gender:Male

Posted 30 November 2015 - 11:02 PM

Hi,

 

1) Yes, you can do this, but DataChanged also refresh grid. Maybe this can be done more efficient. Any tips are welcome.

 

2) You can use something like:

 

NextVirtualGrid61.Columns.SortedColumn.Index

 

I have started implementing MultiSort so later you will be able to read:

 

NextVirtualGrid61.Columns.SortedIndexOf()

boki@bergsoft.net | LinkedIn Profile
--
BergSoft Home Page: www.bergsoft.net
Users Section: users.bergsoft.net
Articles and Tutorials: help.bergsoft.net (Developers Network)
--
BergSoft Facebook page
--
Send us applications made with our components and we will submit them on: www.bergsoft.net/apps.htm. Link to this page will be also set on home page too.

#9 karl

karl
  • Members
  • 52 posts
  • Gender:Male
  • Location:Austria

Posted 01 December 2015 - 12:09 AM

Hi,

 

1) No, DataChanged does only refresh 1 column if called in OnAfterSort. If called elsewhere it doesn't seem to do anything at all.

    Is this a bug or am I simply not using it correctly?

 

2) Thanks, works great.



#10 Boki (Berg)

Boki (Berg)

    Boki (Berg)

  • Forum Admin
  • PipPipPipPipPip
  • 8,191 posts
  • Gender:Male

Posted 01 December 2015 - 05:44 AM

Hi Karl,

 

Now checked, DataChanged doesn't call Invalidate so you can refresh by yourself by calling: NextVirtualGrid61.Invalidate() or RefreshRow etc (if you know which row is changed in your data structure).

 

Inside DataChanged is next code:

 

procedure TNxCustomGrid6.DataChanged;
begin
  if Assigned(ActiveView) then
  begin
    ActiveView.Reset;
    VertScrollBar.Clear(False);
  end;
  UpdateScrollBars; // <---- this helps a lot
end;

boki@bergsoft.net | LinkedIn Profile
--
BergSoft Home Page: www.bergsoft.net
Users Section: users.bergsoft.net
Articles and Tutorials: help.bergsoft.net (Developers Network)
--
BergSoft Facebook page
--
Send us applications made with our components and we will submit them on: www.bergsoft.net/apps.htm. Link to this page will be also set on home page too.

#11 karl

karl
  • Members
  • 52 posts
  • Gender:Male
  • Location:Austria

Posted 01 December 2015 - 05:05 PM

Hi Boki,

 

this works great, it's much faster then calling Refresh() on each row.

 

I made a new demo adding 6000 rows to virtualgrid, and I think it's a bit slow in adding the rows.

 

Also if I resize the form with form scaleby, the grid is kind of slow to respond.

 

Please have a look at my attached sample.

 

Maybe you know some tricks to speed it up? Or you just need to fix one of those early bugs you were talking about :).

 

Regards.

 

Attached File  VirtualGrid_Sample.zip   54.12KB   11 downloads



#12 Boki (Berg)

Boki (Berg)

    Boki (Berg)

  • Forum Admin
  • PipPipPipPipPip
  • 8,191 posts
  • Gender:Male

Posted 01 December 2015 - 07:45 PM

Hi Karl,

Thanks, I will test it,and back,to,you.
boki@bergsoft.net | LinkedIn Profile
--
BergSoft Home Page: www.bergsoft.net
Users Section: users.bergsoft.net
Articles and Tutorials: help.bergsoft.net (Developers Network)
--
BergSoft Facebook page
--
Send us applications made with our components and we will submit them on: www.bergsoft.net/apps.htm. Link to this page will be also set on home page too.

#13 karl

karl
  • Members
  • 52 posts
  • Gender:Male
  • Location:Austria

Posted 01 December 2015 - 07:53 PM

Hi Boki,

 

I just realized that what is making it so slow is calling bestFit.

 

Without bestFit it just takes less then 1ms to show.

 

Is there a way I can speed up bestFit ?



#14 Boki (Berg)

Boki (Berg)

    Boki (Berg)

  • Forum Admin
  • PipPipPipPipPip
  • 8,191 posts
  • Gender:Male

Posted 01 December 2015 - 07:54 PM

Hi Karl,

 

As we suspected, problem is in FitCols, FitRows methods from your example.

 

Maybe they can be optimised a bit, for example to only fit rows that are on screen? 


boki@bergsoft.net | LinkedIn Profile
--
BergSoft Home Page: www.bergsoft.net
Users Section: users.bergsoft.net
Articles and Tutorials: help.bergsoft.net (Developers Network)
--
BergSoft Facebook page
--
Send us applications made with our components and we will submit them on: www.bergsoft.net/apps.htm. Link to this page will be also set on home page too.

#15 Boki (Berg)

Boki (Berg)

    Boki (Berg)

  • Forum Admin
  • PipPipPipPipPip
  • 8,191 posts
  • Gender:Male

Posted 01 December 2015 - 07:56 PM

Update :)

 

I think that best fit rows that are only on screen is best. If you have 100,000 rows to be measured x 6 columns this must take some time.


boki@bergsoft.net | LinkedIn Profile
--
BergSoft Home Page: www.bergsoft.net
Users Section: users.bergsoft.net
Articles and Tutorials: help.bergsoft.net (Developers Network)
--
BergSoft Facebook page
--
Send us applications made with our components and we will submit them on: www.bergsoft.net/apps.htm. Link to this page will be also set on home page too.

#16 karl

karl
  • Members
  • 52 posts
  • Gender:Male
  • Location:Austria

Posted 01 December 2015 - 08:01 PM

Ok :)

 

but how can I obtain which rows are on the screen ?

 

Also I tried only calling fitCols, it is faster but also takes about 0,6 seconds. I think becouse it has to iterate over the entire grid to get the width of the largest cell in the column?

 

How to solve this?



#17 Boki (Berg)

Boki (Berg)

    Boki (Berg)

  • Forum Admin
  • PipPipPipPipPip
  • 8,191 posts
  • Gender:Male

Posted 01 December 2015 - 08:23 PM

Hi Karl,

I will play with it to see how to speed it up.

Yes, it must measure all of them. Is it maybe possible to know which cell will be largest in your data and then only measure it?
boki@bergsoft.net | LinkedIn Profile
--
BergSoft Home Page: www.bergsoft.net
Users Section: users.bergsoft.net
Articles and Tutorials: help.bergsoft.net (Developers Network)
--
BergSoft Facebook page
--
Send us applications made with our components and we will submit them on: www.bergsoft.net/apps.htm. Link to this page will be also set on home page too.

#18 karl

karl
  • Members
  • 52 posts
  • Gender:Male
  • Location:Austria

Posted 01 December 2015 - 08:37 PM

Thanks, Boki please keep me posted.

 

Yes I guess I could do that. But, theoratically if somehow obtain ( in my own code) which Cell of a column in my datastructure is the largest one.

 

How do I then obtain it's width and height in the grid?

I think would need something like bestFitCellWidth and bestFitCellHeight (should return width and height) to measure it.

 

Then I would have to set Column-width and Row-height properties manually.

Do you have an example for this ?



#19 karl

karl
  • Members
  • 52 posts
  • Gender:Male
  • Location:Austria

Posted 01 December 2015 - 08:47 PM

Or maybe this could be done with the cell.canvas property ? So I could measure the text-extent correctly.

 

Anyways, I'm not entirely sure how to approach this.

 

Some code would be very helpfull.



#20 karl

karl
  • Members
  • 52 posts
  • Gender:Male
  • Location:Austria

Posted 01 December 2015 - 09:36 PM

I now managed to obtain the maximum Column text-extent and row height of my structures using grid.Canvas and store it in an array.
 
This takes a couple of ms. I'm not sure why it's so slow in your bestFit-procedures. Maybe there is something else going on there?
 
Though I don't know how to set the Row height manually, could you please guide me on this issue?
 
The Column width I set like this now:
 

 nxTxtCol.width := fWidths[ 0 ];  //for first column

 

However typing this for every column in the gird is a tedious task, so I wonder I there is some way to loop over all Columns like:

 

for i := 0 to grid.ColCount-1 do

  grid.Col[ i ] := fWidths[ i ];                      // maybe there is some property I overlooked ?

 

Thanks for the great support, Karl.






1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users