Forum > RichMemo

[SOLVED]Searching a term in Richmemo becomes very slow

(1/2) > >>

ariben:
Hi folks,
As I execute the following code the the Richmemo becomes very slow. Even the search term is only one.
Could anybody speed this up?

--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---procedure TForm2.DBGrid1DrawColumnCell(Sender: TObject; const Rect: TRect;  DataCol: Integer; Column: TColumn; State: TGridDrawState);var  fp   :  TFontParams;  PosSW1, PosSW2, PosSW3: Integer;  i : Integer; begin    fp.Color := clRed;    fp.Style := [fsBold];    fp.Size := 13;    fp.BkColor := clWhite;     if gdSelected in State then  //<---Everything was fine before added this!!!    RichMemo1.Text:= Column.Field.AsString;            //RichMomo1に内容を表示する     for i := 0 to UTF8Length(RichMemo1.Text) do                 //1語ずつケツ迄読んで    begin                                                       //検索語を探す    PosSW1 := RichMemo1.Search(SW1, i, UTF8Length(SW1), []);    //UTF8Length()を使うためには    RichMemo1.SetTextAttributes(PosSW1, UTF8Length(SW1), fp);   //LazUtils, LazUTF8が必要    if SW2 <> '' then       begin       PosSW2 := RichMemo1.Search(SW2, i, UTF8Length(SW2), []);       RichMemo1.SetTextAttributes(PosSW2, UTF8Length(SW2), fp)       end;       if SW3 <> '' then       begin       PosSW3 := RichMemo1.Search(SW3, i, UTF8Length(SW3), []);       RichMemo1.SetTextAttributes(PosSW3, UTF8Length(SW3), fp)       end;   end;end;

TRon:
disclaimer: I am not familiar with Richmemo

Your loop ...

--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---for i := 0 to UTF8Length(RichMemo1.Text) do ... Is more or less redundant because search already searches through all the richmemo contents (if I understood your search pattern correctly)

When you use the loop the search for SW1 is executed UTF8length(Richmemo1.text) times. That can literally take a very long time  :)

Imho a possible (not tested) option could be to replace that loop with something like

--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---posSW1 := 0;while posSW1 < UTF8Len(Richmemo1.Text) and posSW1 <> -1 dobegin  PosSW1 := RichMemo1.Search(SW1, PosSW1, UTF8Len(Richmemo1.Text) - PosSW1, []);  // set attributeend; // similar loop for SW2 // similar loop for SW3  That is if I understood your code and the wiki correctly. Note that the snippet above does not take the length of SW1 into consideration (which can speed things up even further especially when the length of SW1 is considerable).

PS: I do not know where your richmemo component is situated but realize that DrawGridColumnCell can be invoked many times when scrolling your grid. Basically each time the gridcell needs to be repainted. Doesn't richmemo have an event that is triggered when you assign contents to it ? That would be a much more suitable location to set your attributes.

TRon:
1. You do not seem to filter out the 'correct' record field (row) which, in case you show multiple rows at once (columns as well) means that every time the drawgridColumnCell
is triggered (which is for every visible and selected (see gdSelected in state) row/column) your search method(s) are executed.

For now, I leave that for/to yourself to address (and in case you want to).

2. the outer-loop (for i := 0 to UTF8Length(RichMemo1.Text) is unnecessary (as already mentioned before). Simply remove that, see also snippet posted below.

3. You are providing the length of your search term to the call to the richmemo search method (which is wrong, it should be the length of the content to search in , e.g. the length of the Memo contents (the earlier posted code-snipped showed that already). See earlier posted snippet and updated snippet below (which now also takes the length of the search term into consideration and skips it).

4. The loops with the Search and SetTextAttributes methods should be executed somewhere else. I tried to set the text using the text property but unfortunately that does not seem to trigger an onchange event. Also Update and invalidate where not able to trigger an OnChange Event so I have no clue which event to use to perform your search and highlighting routines.

The snippet below seem to work for me (except the aforementioned issues). I leave it up to you to address the length/UTF8len/UTF8Length mayhem's.


--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---procedure TForm1.PerformHighLight;var  fp          : TFontParams;  posSW1      : integer = 0;  SearchTerm1 : string = 'text to search for';begin  fp.Color := clRed;  fp.Style := [fsBold];  fp.Size := 13;  fp.BkColor := clWhite;   posSW1 := 0;  while (posSW1 < RichMemo1.GetTextLen) and (posSW1 <> -1) do  begin    PosSW1 := RichMemo1.Search(SearchTerm1, PosSW1, RichMemo1.GetTextLen - PosSW1, []);    if posSW1 > 0 then    begin      // set attribute      RichMemo1.SetTextAttributes(PosSW1, Length(SearchTerm1), fp);      // next search-position      inc(PosSW1, Length(SearchTerm1));    end;  end;   // repeat for SW2 and SW3end; 

ariben:
Dear Tron,

Thank you very much for your code.  I was working almost all night long on this.
Your code works fine. But It's 7:00 in the morning in Japan so I need to go to my work place. Let me allow some more time to examine the detail.

And I didn't know the repaint of the grid so frequently. Now I know OnDrawColumn event is not appropriate for this action as you mentioned(as the window locks on this event).

Catch you later.

TRon:

--- Quote from: ariben on January 30, 2024, 11:20:59 pm ---Thank you very much for your code.  I was working almost all night long on this.

--- End quote ---
Thank you for trying and confirming that it works for you.


--- Quote ---Let me allow some more time to examine the detail.

--- End quote ---
No problem, take your time and in case of questions just ask. I don't know much about Richmemo but I have to figure it out myself eventually as well.


--- Quote ---And I didn't know the repaint of the grid so frequently. Now I know OnDrawColumn event is not appropriate for this action as you mentioned(as the window locks on this event).

--- End quote ---
It depends entirely on your actual situation.

If you have a dbgrid with only one visible row or column then the event is triggered much less while having a full grid visible on your form calls the event for every cell it needs to (re)draw. The event at least allows to filter out by checking which field(name) is drawn. Usually the datasource is used to figure out which row is currently active but I can understand that your goal is to view the text (detailed in a richmemo) for the cell/row/column that is currently selected (by the user).

If you want to know how many time's the event is actually fired then place a temporary memo on your form next to your grid and append a line of text (preferably a counter) to that memo in the grid's DrawColumnCell event. It is a total waste of precious time to read the text from the database, assign it to a richmemo and perform highlighting for every time the event is fired. Your code needs to be performed only when the user changes from one row/column to another (if you have set it up that way) or when a change in the selection of a specific text field (in de grid) occurred.

Till next time  :)

Navigation

[0] Message Index

[#] Next page

Go to full version