Спящий режим работает только в режиме отладки, но не в режиме выпуска (Embarcadero C ++ Builder)

Я использую Embarcadero C ++ Builder (инженер, а не программист)

Я считаю, что функция сна работает у меня только в режиме отладки, а не в режиме выпуска. Я вижу ссылки в StackOverFlow не на использование Sleep, а на использование TTimer.

Я просто хочу, чтобы мое приложение приостанавливалось на несколько секунд между рисованием объектов согласно Sleep (500); в приведенном ниже коде, чтобы я мог видеть каждый рисуемый объект и проверять их правильность, иначе проверка будет слишком быстрой.

DrawSelectedShape (k, сторона, AddOrDeduct, Color); в приведенном ниже коде - это процесс, требующий приостановки.

for (int n=0; n<LiquidLoads->TankBasicData->NoLiquidTypes; ++n){
  for (int m=0; m<LiquidLoads->TankBasicData->NumberOfTanks[n]; ++m)
  {
    for (int l=1; l<LongStrengths->TotalNumberOfParts+1; ++l)
     {
       if (LiquidLoads->TankHeaderArray[n][m]->GhsName == LongStrengths->PartHeader[l]->PartName)
       {

         for (int j=0; j<LongStrengths->PartHeader[l]->NoOfComponents; ++j)
         {
            int k = LongStrengths->PartData[l][j]->ShapeNumber;
            int Side = LongStrengths->PartData[l][j]->Side;
            float AddOrDeduct = LongStrengths->PartData[l][j]->Effectiveness;
            AnsiString Color = LiquidLoads->TankBasicData->LiquidTypeColor[n];
            DrawSelectedShape(k,Side,AddOrDeduct,Color);

            Canvas->TextOut(1200, 300+(n*25),LiquidLoads->TankBasicData->LiquidType[n]);
            Sleep(300);
         }
       break;
       }
   }
}  }

Приведенный выше код отлично работает в режиме отладки, но в режиме выпуска он отлично работает, когда первые несколько фигур отображаются на холсте, затем на некоторое время появляется курсор мыши с вращающимся колесом, за которым следует пустой холст.

Поэтому ищу альтернативу Sleep.

При использовании TTimer (без опыта) можно использовать событие OnTimer и разместить код, который многократно запускается в событии с задержкой, связанной с интервалом Timer1, что не совсем то же самое, что просто искать задержку в несколько секунд посередине. цикла for

Вот как выглядит мой рендеринг:

анимация

Любой совет, очень ценимый.


person BarryK    schedule 15.10.2018    source источник
comment
Sleep() - это функция Win32 API, она работает в точности одинаково в режимах отладки и выпуска. Просто очень сложно отладить операции рисования таким образом с самого начала. Как только вы переключаетесь между пользовательским интерфейсом и другим окном, таким как отладчик или редактор кода, пользовательский интерфейс получает сигнал перерисовать себя, стирая предыдущие рисунки. Кроме того, очень плохо вводить задержки во время обработки отрисовки, поскольку ОС, вероятно, будет жаловаться на то, что отрисовка занимает слишком много времени и замедляет последующую обработку сообщений пользовательского интерфейса.   -  person Remy Lebeau    schedule 15.10.2018
comment
Вам действительно нужно переосмыслить свой подход к отладке. Я бы предложил обновить DrawSelectedShape(), чтобы дать ему входной параметр TCanvas, и позволить ему рисовать на этом холсте по мере необходимости. Затем вы можете создать TBitmap для каждой фигуры, которую хотите нарисовать, и передать TBitmap.Canvas DrawSelectedShape(). Затем вы можете просматривать TBitmaps по мере необходимости, например, сохраняя их в .bmp файлах или отображая их в TImage элементах управления и т. Д.   -  person Remy Lebeau    schedule 15.10.2018
comment
Большое спасибо, Реми. Мне нужно будет изучить опцию TBitmap для целей отчетности, поскольку я использую FastReports и мне нужно добавить Canvas в отчет, однако для этого экранного сценария мне нужен эффект задержки не только для отладки, но и как опция пользователя. Причина в том, что он рисует танки корабля в плане, и некоторые танки расположены над другими. Если вы позволите ему нарисовать все сразу, вы увидите только то, что находится наверху, тогда как пользователю нужна возможность позволить ему рисовать их немного более анимированным образом. Я понятия не имею, почему Sleep хорошо работает в режиме отладки, а не в режиме выпуска.   -  person BarryK    schedule 15.10.2018
comment
Тогда вам понадобится совершенно другой подход к своему рисунку. Использование Sleep() неправильно, TTimer имеет больше смысла. Было бы лучше, если бы таймер нарисовал все на одном TBitmap, а затем вы могли бы нарисовать текущий TBitmap на выбранной вами цели Canvas всякий раз, когда ее нужно раскрасить. Пока не закончите, тяните по одному танку за каждое событие таймера. Например, в случае TForm вы можете настроить таймер на обновление TBitmap по мере необходимости, а затем Invalidate() Форму для запуска перерисовки, а затем нарисовать текущий TBitmap на Canvas Формы в событии OnPaint Формы.   -  person Remy Lebeau    schedule 15.10.2018
comment
Большое спасибо Реми. Оценил как всегда. Я буду развивать маршрут TTimer & TBitmap. (В моих предыдущих трех вопросах был способ принять ответ. Здесь это не очевидно. Считайте, что ответ принят, а сообщение закрыто.)   -  person BarryK    schedule 16.10.2018
comment
В моих трех предыдущих вопросах был способ принять ответ. Здесь это не очевидно - потому что ответа не было, только комментарии с предложениями   -  person Remy Lebeau    schedule 16.10.2018
comment
@BarryK взгляните на это: Как замедлить чтение анимации opengl из файлов BVH? и Управление последовательностью спрайтов с помощью DeltaTime для получения некоторых основ о времени анимации. К сожалению, без предварительного просмотра мы понятия не имеем, что и как вы визуализируете. Могут быть другие способы представления вашей сцены (без анимации), такие как переключение в 3D, использование прозрачности или какой-то слайдер, выбирающий видимый слой и т. Д. Также в каком событии находится ваш фрагмент кода?   -  person Spektre    schedule 18.10.2018
comment
@BarryK Потому что я также столкнулся с этим. В некоторых случаях время между запуском внутри Embarcadero IDE и запуском напрямую exe без IDE очень различается. У меня есть проект с множеством форм, для каждой из которых требуются довольно дорогие сроки / обновления. В IDE все тайминги в порядке, но без него частота таймеров и событий падает до менее чем половины запрограммированных значений ... Но в моем случае я подозреваю, что это также может быть проблема с скрытым нарушением доступа, перезаписывающая исходные данные / код, который не манифест в IDE (уже несколько раз видел такое поведение ...)   -  person Spektre    schedule 18.10.2018
comment
Если вам нужно визуально проверить, правильно ли нарисован графический элемент, лучше всего ввести способ закрасить только этот элемент (или, по крайней мере, не закрасить элементы, которые могут его скрыть).   -  person n. 1.8e9-where's-my-share m.    schedule 19.10.2018
comment
@BarryK да, делиться дополнительными ссылками за пределами сайта - это нормально, но иметь ответ или вопрос, который зависит только от ссылки за пределами сайта, - это не нормально, поскольку они имеют тенденцию к разрыву со временем, и тогда такие вопросы или ответы будут бесполезны. В таком случае хорошо бы повторить, что делает ссылка, и назвать ее источником знаний ... Я создал GIF из вашего видео и добавил его к вашему вопросу, поэтому нам не нужно нажимать на внешние ссылки :)   -  person Spektre    schedule 19.10.2018


Ответы (2)


ну из видео, которое вы разместили, его четкая анимация с использованием таймера - это лучший способ ...

Из вашего описания У вас должно быть какое-то значение ix для каждого видимого объекта на вашем корабле. Сообщая слой или порядок рендеринга объекта.

Поэтому добавьте значение render_ix в свой код рендеринга (глобальный или член формы, в которой вы рендерит), а затем перекодируйте свою процедуру рисования на это:

int render_ix=0; // order/layer number for object to render up to

void draw()
 {
 // here clear&render background
 for (int i=0;i<objects;i++)
  if (object[i].ix<=render_ix)
   object[i].draw(); // render i-th object
 // here render HUD
 }

теперь просто где-то в вашем таймере с желаемым интервалом

void OnTimerAnimation()
 {
 render_ix++;
 if (render_ix>=objects) render_ix=0;
 // here force repaint either by calling Paint, Refresh,Update ... or what ever way you are using
 }

Вы также можете изменить render_ix с помощью полосы прокрутки или программно. Как видите, Sleep или Delay не требуется, следовательно, не требуется блокировка выполнения.

Если ваш рендеринг основан не на порядке объектов, а на некоторой фильтрации, просто измените render_ix с переменной, которую вы фильтруете. Таким образом, вы можете вложить больше переменных (объем, масса, положение ...) во вложенные if операторы.

Еще одна, но очень полезная схема - использовать выборки. Итак, создайте список индексов объектов для рендеринга ... и рендеринг / выделите только те, которые присутствуют в списке. Это очень полезно для выделения мышью и работы с несколькими контейнерами одновременно.

person Spektre    schedule 19.10.2018
comment
Спасибо. Это очень полезный совет. В качестве теста я могу попробовать инкремент render_ix в таймере, как вы указали, однако для фактического приложения мне придется следовать вашему предложению по выбору, так как объекты для рендеринга не обязательно в порядке. Оценил как всегда. - person BarryK; 19.10.2018

Чтобы избежать циклов for и if, которые были частью процесса рисования на холсте с использованием метода Sleep для приостановки циклов, теперь мне сначала пришлось сгенерировать последовательность визуализации для Struct, которую я мог затем использовать с одним последовательный счетчик в TTimer

как показано ниже

//---------------------------------------------------------------------------
void __fastcall TShipGraphic::DrawSelectedTanksBtnClick(TObject *Sender)
{
    GenerateRenderSequence();
    Timer1->Interval = StrToInt(Edit1->Text);
    CloseButton->Enabled = false;
    render_ix=0; //Initialised globally

     Timer1->Enabled = true;

}
//---------------------------------------------------------------------------
void __fastcall TShipGraphic::Timer1Timer(TObject *Sender)
{
 render_ix++;
 Timer1->Interval = StrToInt(Edit1->Text);
 if (render_ix<=TankShapeCounter)
 {
    DrawSelectedComponentShape(render_ix); // render i-th object
    Canvas->Refresh();
 }
 else
 {
   Timer1->Enabled = false;
   CloseButton->Enabled = true;
 }
}
//---------------------------------------------------------------------------
void TShipGraphic::GenerateRenderSequence()
{
   TankShapeCounter = 0;

  for (int n=0; n<LiquidLoads->TankBasicData->NoLiquidTypes; ++n)
  {
    if ((CheckListBox1->Checked[n]) || (CheckListBox1->Checked[LiquidLoads->TankBasicData->NoLiquidTypes]))
    {
      for (int m=0; m<LiquidLoads->TankBasicData->NumberOfTanks[n]; ++m)
      {

        for (int l=1; l<LongStrengths->TotalNumberOfParts+1; ++l)
         {
           if (LiquidLoads->TankHeaderArray[n][m]->GhsName == LongStrengths->PartHeader[l]->PartName)
           {

             for (int j=0; j<LongStrengths->PartHeader[l]->NoOfComponents; ++j)
             {
                ++TankShapeCounter;
                int k = LongStrengths->PartData[l][j]->ShapeNumber;
                int Side = LongStrengths->PartData[l][j]->Side;
                float AddOrDeduct = LongStrengths->PartData[l][j]->Effectiveness;
                AnsiString Color = LiquidLoads->TankBasicData->LiquidTypeColor[n];
                RenderSequence[TankShapeCounter]->ShapeNumber = k;
                RenderSequence[TankShapeCounter]->Side = Side;
                RenderSequence[TankShapeCounter]->AddOrDeduct = AddOrDeduct;
                RenderSequence[TankShapeCounter]->Color = Color;
             }
           break;
           }
         }
      }
    }
  }
}
//---------------------------------------------------------------------------

Я хотел использовать аккуратный метод анимированных gif @ Spectre, чтобы показать результат, но моя игровая панель слишком темпераментна, чтобы захватывать экранную анимацию в видео. «Win G» для активации игровой панели ничего не делает.

Спасибо Реми и Спектру за ценные советы.

person BarryK    schedule 22.10.2018