Hallo zusammen,
nach einer langen Pause habe ich mir nun endlich wieder die Zeit genommen, an diesem Projekt weiter zu arbeiten.
Aktuell beschäftigt mich immer noch das Zeichnen. Aktuell mache ich das folgendermaßen (ich benutze die GR32-Komponente):
Ich habe folgendes Interface, das mir den Inhalt der Radarfläche kapselt:
Delphi-Quellcode:
IRadarScreen = interface(IBaseInterface)
function GetContent: TImage32;
/// <summary>The image-information which shall be displayed.</summary>
/// <remarks>The interface will free the content when implementation is freed. Do not
/// hold a reference to the content unless you are sure that implementation lives longer than
/// your reference!</remarks>
property Content: TImage32 read GetContent;
end;
Ganz innen habe ich einen Thread zum Zeichnen. Dieser erzeugt eine TImage32-Instanz mit den gewünschten Bitmap-Layern und verpackt diese Instanz im IRadarScreen-Interface. Über eine Callback-Methode reicht der Thread dieses Interface nach außen. Hier mein aktueller Code:
Delphi-Quellcode:
procedure TDrawerThread.Run;
var
radarScreen: IRadarScreen;
begin
inherited;
while not Terminated do
begin
radarScreen := TestRadarScreenUpdate; // diese Methode erzeugt die TImage32-Instanz und liefert dieses als IRadarScreen-Interface zurück.
if Assigned(FOnDrawSuccess) then
Synchronize(procedure
begin
FOnDrawSuccess(radarScreen)
end);
sleep(33);
end;
end;
(Später soll dieser Code immer dann getriggert werden, wenn etwas neu gezeichnet werden muss, sei es durch eine Neuberechnung der Positionen in der Simulation oder durch ein Resize der Radar-Fläche. Die Prozedur FOnDrawSuccess wird per Constructor-Injection an den Thread übergeben)
Das IRadarScreen-Interface wird dann über verschiedene Schichten im Model an den Presenter und von dort an mein View übergeben. Das View hat schließlich Zugriff aufs Formular und führt bei einem Update folgenden Code aus:
Delphi-Quellcode:
procedure TMainView.SetRadarScreen(const UpdatedRadarScreen: IRadarScreen);
var
radarScreenRefOld: IRadarScreen;
begin
// ensure that the old IRadarScreen is freed only after the reference to its image has been removed!
radarScreenRefOld := FRadarScreenRef;
FRadarScreenRef := UpdatedRadarScreen;
if Assigned(FRadarScreenContent) then
FRadarScreenContent.Parent := nil;
FRadarScreenContent := UpdatedRadarScreen.Content;
radarScreenRefOld := nil;
FRadarScreenContent.Parent := Form.pnlRadar;
FRadarScreenContent.Left := 0;
FRadarScreenContent.Top := 0;
end;
Kurz gesagt heißt das, dass ich immer die komplette TImage32-Instanz auf dem Formular austausche. Ich habe es schon einmal mit TImage32.Assign ausprobiert, aber das liefert eine
Exception, weil man TImage32 das zuweisen auf diese Art wohl nicht unterstützt.
Da ich bisher noch kaum Erfahrung mit dem Zeichnen/Neuzeichnen habe, wollte ich mal fragen, ob meine Implementierung vllt. zu unerwünschten Effekten führen könnte (weil ich immer das komplette TImage32-Objekt austausche) und ob es da vllt. bessere Möglichkeiten gibt.