I am using Embarcadero C++ Builder (an engineer not programmer)
I find the Sleep function is only working for me in debug mode and not in release mode. I see references in StackOverFlow not to use Sleep, and rather to use TTimer.
I simply want my app to pause for a few seconds between drawing objects as per the Sleep(500); in the code below, so that I can see each object being drawn and can check they are correct, else it happens to fast to check.
DrawSelectedShape(k,Side,AddOrDeduct,Color); in the below code, is the process that needs pausing
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;
}
}
} }
The above code works perfectly in debug mode, but in release mode, it works fine through the first few shapes being drawn to canvas, then you get a spinning wheel mouse cursor for a while followed by a blank canvas.
So I am looking for an alternative to Sleep.
When using a TTimer (no experience) one would use the OnTimer event, and place code that runs repeatedly in the event with a delay related to the Timer1 Interval, which is not quite the same as just looking for a few seconds delay in the middle of a for-loop
This is how my rendering looks like:
Any advise, most appreciated.
well from the video you posted its clear animation using timer is the way to go...
From your description You should have some value ix
for each visible object on your ship. Telling the layer or rendering order of the object.
So add a render_ix
value to your rendering code (either global or a member of the form where are you rendering) then recode your draw routine to this:
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
}
now just somwhere in your timer with desired interval
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
}
You can also change the render_ix
by scroll bar or programaticaly. As you can see no Sleep
or Delay
is needed hence no blocking of execution.
If your rendering is not order of object based but radher by some filtering than just change the render_ix
with the variable you are filtering. This way you can nest more variables together (Volume, mass , position...) into nested if
statements.
Another but very useful scheme is to use selections. So create a list of object indexes to render... and render/highlight only those that are present in the list. That is very useful for mouse selections and operation with more containers at once.
To avoid the for loops and if statements, that was part of the process of drawing to the canvas using the Sleep method to pause the loops, I now first had to generate a render sequence to a Struct, that I could then use with a single sequential counter in TTimer
as below
//---------------------------------------------------------------------------
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;
}
}
}
}
}
}
//---------------------------------------------------------------------------
I wanted to use @Spectre's neat animated gif method to show the result, but my Game Bar is too temperamental to capture the screen animation to a video. "Win G" to activate the Game Bar is doing nothing.
Thanks to Remy and Spektre for the valuable advise.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.