1

Тема: Заміна частин тексту в полі Memo в Delphi

У мене виникли питання із заміною тексту в Memo
Задумом такий:- у додатку з три поля  Memo. З першого поля Memo копіюю рядки у змінну, ділю її на три частини, а тими частинами заміняю текст у двох інших полях Memo.

Проблема в тому що додаток дуже тормозить і підвисає, хоча той результат що я задумав - видає.
Підкажіть що в коді не так, буду щиро вдячний

procedure TMainForm.sbtDecodeTextClick(Sender: TObject);
//mm-це приставка до компонентів Memo
//ed-це приставка до компонентів Edit
var
  iCopyLines:integer;//Порядковий номер рядка в мемо
  iSizeLines:integer;//Кількість символів у рядку
  iNumLetterS:integer;//Порядковий номер символу "\" у рядку
  iNumLetterES:integer;//Порядковий номер символу "=" у рядку
  sLines:String;//Скопійований рядок з мемо1
  sLetter:String;//Частина рядка до знаку "\"
  sKodeTrue:String;//Частина рядка між знаками "\" та "="
  sKodeFalse: String;//Частина рядка після знаку "="
begin
//---  Тут ми зозбиваємо строку з Memo1 на три частини  ---
//----------------------------------------------------------
  for iCopyLines:=0 to mmCode.Lines.Count-1 do
    begin
      sLines:=mmCode.Lines[iCopyLines];//копіюємо строку у змінну з Memo1
      with mmCode do//виділяємо текст(цілий рядок) у Memo1
        begin
          SetFocus();
          SelStart:=Pos(sLines,mmCode.Lines.Text)-1;
          SelLength:=Length(sLines);
        end;
      iSizeLines:=Length(sLines);//знаходимо кількість символів строки
      iNumLetterS:=Pos('\',sLines);//дізнаємося порядковий номер символу "\"
      iNumLetterES:=Pos('=',sLines);//дізнаємося порядковий номер символу "="
      sLetter:=Copy(sLines,1,iNumLetterS-1);//копіюємо частину рядка до знаку "\"
      edLetter.Text:=sLetter;//записуємо у поле Edit1
      sKodeTrue:=Copy(sLines,iNumLetterS,iNumLetterES-iNumLetterS);//копіюємо частину рядка між знаками ("\"-1)та "="
      edKodeTrue.Text:=sKodeTrue;//записуємо у поле Edit2
      sKodeFalse:=Copy(sLines,iNumLetterES+1,iSizeLines-iNumLetterES);//копіюємо частину рядка після знаку "="
      edKodeFalse.Text:=sKodeFalse;//записуємо у поле Edit3
//--- Тут ми замінюємо частини тексту у полях Memo2 та Memo3 ---
//-----------------------------------------------------------
      if Pos(sKodeFalse,mmText.Lines.Text)<>0 then//Якщо є такий фрагмент тексту то замінюємо його
        begin            {
          with mmText do
            begin
              SetFocus();
              SelStart:=Pos(sKodeFalse,mmText.Lines.Text)-1;
              SelLength:=Length(sKodeFalse);
            end;  }
          mmText.Lines.Text:=StringReplace(mmText.Lines.Text,sKodeFalse,sKodeTrue,[RFREPLACEALL]);//Замінюємо частини тексту у Memo2
          mmTextVisible.Lines.Text:=StringReplace(mmTextVisible.Lines.Text,sKodeFalse,sLetter,[RFREPLACEALL]);//Замінюємо частини тексту у Memo3
        end
          else
        begin
          if Pos(sKodeTrue,mmTextVisible.Lines.Text)<>0 then //Якщо є такий фрагмент тексту то замінюємо його
            begin
              mmTextVisible.Lines.Text:=StringReplace(mmTextVisible.Lines.Text,sKodeTrue,sLetter,[RFREPLACEALL]);//Замінюємо частини тексту у Memo3
            end;
        end;
    end;  
  ShowMessage('Завершено');
end;

2

Re: Заміна частин тексту в полі Memo в Delphi

Поясніть, будь ласка, нащо ви в циклі виділяєте текст у mmCode? Загальний принцип - процесор швидкий, введення та виведення повільні. Виділення, зокрема, змінює зображення, тому повільне. Там ще багато є питань, але почнемо з цього. Якщо вам потрібно в результаті щось виділити - виділяйте після циклу.
Те саме стосується і присвоювання TMemo.Lines, зокрема TMemo.Lines.Text. Якщо хочете щось зробити - зробіть його всередині коду, а потім присвоюйте, не робіть це в циклі обробки.
Ну і назви... загалом це добре, що ви даєте повні назви змінним, але все ж бажано більше літер витрачати на суть. Скажімо, iNumLetterS - ви скоротили "slash" до "s", хоча по суті саме це і відрізняє цю змінну. Як вам iSlashPos - позиція (pos - стандартна функція, скорочення прийнятне) дробу (slash) типу integer?

Подякували: Romanvolja1

3 Востаннє редагувалося Romanvolja (21.09.2020 16:44:51)

Re: Заміна частин тексту в полі Memo в Delphi

Поле mmCode знаходиться праворуч два інші поля Memo знаходяться ліворуч(одне з яких приховане, за потреби я їх перемикаю)
Тут скріншот
Призначення додатку: виправлення текстового шару електронних книг графічних форматів(Djvu)
Бувають електронні книги коли при копіюванні тексту замість тексту виходять каракулі
Докладніше в темі на форумі

В праве поле я завантажую текстовий шар(з електронної книги), а в ліве(mmCode)завантажую коди для перекодування тексту

Текст в полі mmCode виглядає так

А\320\220=\303\200
а\320\260=\303\240
БІ\320\221\320\206=\303\2012
Бі\320\221\321\226=\303\2013
бі\320\261\321\226=\303\2413
Б\320\221=\303\201
б\320\261=\303\241
ВІ\320\222\320\206=\303\2022
Ві\320\222\321\226=\303\2023
ві\320\262\321\226=\303\2423
В\320\222=\303\202
в\320\262=\303\242
ГІ\320\223\320\206=\303\2032

Задум в мене такий:
1-В процесі for вибираю з поля mmCode вибираю першу строку(А\320\220=\303\200)
2-далі ділю її на три частини
А-буква
\320\220-правильний код букви
\303\200-не правильний код букви
3-щоби в полі mmText(Memo) замінити всі не правильний код букви на правильним кодом букви
4-А для контролю і візуального перегляду результату у полі mmTextVisible(Memo) заміную всі не правильний код букви на саму букву(в даному випадку А)
5-Далі йде другий цикл витягується другий рядок (а\320\260=\303\240)

koala написав:

Поясніть, будь ласка, нащо ви в циклі виділяєте текст у mmCode?

Щоби бачити процес(хід) роботи

koala написав:

Те саме стосується і присвоювання TMemo.Lines, зокрема TMemo.Lines.Text. Якщо хочете щось зробити - зробіть його всередині коду, а потім присвоюйте, не робіть це в циклі обробки.

Ви маєте на увазі це:

mmText.Lines.Text:=StringReplace(mmText.Lines.Text,sKodeFalse,sKodeTrue,[RFREPLACEALL]);//Замінюємо частини
koala написав:

але все ж бажано більше літер витрачати на суть. Скажімо, iNumLetterS - ви скоротили "slash" до "s"

Я спочатку змінним дав такі назви:
iNumLetterReverseSolidus:integer;
iNumLetterEqualsSign:integer;
а потім скоротив, та бачу що не варто було скорочувати, дякую за пораду

4

Re: Заміна частин тексту в полі Memo в Delphi

Підтримаю koala, викиньте усю взаємодію із візуальними елементами із циклу. Якось так:

procedure TMainForm.sbtDecodeTextClick(Sender: TObject);
var
  ...
  CodeLines: TStringList;
  TextLines: String;
begin
  TextLines := mmText.Lines.Text;
  CodeLines := TStringList.Create;
  try
    CodeLines.Assign(mmCode.Lines);
    for iCopyLines:=0 to CodeLines.Count-1 do
    begin
      sLines:=CodeLines[iCopyLines];//копіюємо строку у змінну з Memo1
      ...
            TextLines :=StringReplace(TextLines, sKodeFalse,sKodeTrue,[RFREPLACEALL]);//Замінюємо частини тексту у Memo2
      ...
    end;
  finally
    CodeLines.Free;
  end;
  mmText.Lines.Text := TextLines;
  ShowMessage('Завершено');
end;
Подякували: Romanvolja1

5

Re: Заміна частин тексту в полі Memo в Delphi

В гіршому разі робіть 1 виділення на певний час, скажімо, якщо вже минуло 100мс з попереднього.

Подякували: Romanvolja1

6

Re: Заміна частин тексту в полі Memo в Delphi

Torbins написав:

Підтримаю koala, викиньте усю взаємодію із візуальними елементами із циклу. Якось так:

Щиро дякую за допомогу. Переробив зараз набагато краще працює