AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Canvas: Änderungen/Bewegungen zeichnen

Ein Thema von Scurra · begonnen am 26. Aug 2018 · letzter Beitrag vom 2. Jan 2020
Antwort Antwort
Seite 2 von 3     12 3      
Benutzerbild von jaenicke
jaenicke

Registriert seit: 10. Jun 2003
Ort: Berlin
9.648 Beiträge
 
Delphi 11 Alexandria
 
#11

AW: Canvas: Änderungen/Bewegungen zeichnen

  Alt 29. Aug 2018, 22:25
Ob ich nun direkt eine Paintbox zeichne oder ein Bitmap verwende, weiß ich noch nicht genau.
Du solltest in jedem Fall alles erst fertig in ein Bitmap zeichnen und dann in einem Rutsch dieses in die Paintbox kopieren. Ansonsten flackert es nur unnötig.
Sebastian Jänicke
AppCentral
  Mit Zitat antworten Zitat
Scurra

Registriert seit: 19. Jan 2015
81 Beiträge
 
Delphi 10.3 Rio
 
#12

AW: Canvas: Änderungen/Bewegungen zeichnen

  Alt 1. Sep 2018, 12:39
Ich habe gestern und heute mal ein wenig herumgespielt. Da ich das graphics32-Package schon hatte, habe ich dieses verwendet (ich dachte bislang, dass das schon standardmäßig in Delphi enthalten ist ). Mit der TImage32-Komponente und den darin enthaltenen (Bitmap-)Layern klappt das bisher wunderbar. Das einzige, das ich etwas störend/umständlich finde, sind die runden Enden von Linien, die man mit der Methode LineTo auf die Bitmaps zeichnet. Ich habe hier im Forum schon eine Lösung dafür gefunden (https://www.delphipraxis.net/92808-t...ten-ecken.html), man muss aber extra jedes Mal die Winapi verwenden.

Ich habe gerade noch eine Frage: Was ich bei meiner Anforderung komplett vergessen habe, ist, dass man das Formular auch vergrößern und verkleinern kann. Wie würdet ihr in einem solchen Fall vorgehen? Im Moment mache ich es so, dass ich die TImage32-Komponente mit alClient über mein Radar-Panel setze. Die Maße der Bitmaps in den Layern müsste ich aber im OnResize auch ständig anpassen, was evtl. zu einem Flackern führen könnte, wenn man das Formular mit der Maus groß/klein zieht (das OnResize-Event wird dann oft ausgelöst).
  Mit Zitat antworten Zitat
Benutzerbild von stahli
stahli

Registriert seit: 26. Nov 2003
Ort: Halle/Saale
4.343 Beiträge
 
Delphi 11 Alexandria
 
#13

AW: Canvas: Änderungen/Bewegungen zeichnen

  Alt 1. Sep 2018, 15:54
In meinem Projekt berechne ich das Bitmap in einem Thread. Für die Berechnung wird die Zielgröße ClientRect des Formulars mitgegeben.
Wenn die Berechnung fertig ist, wird das Bitmap synchronisiert auf den Formularcanvas kopiert.

Sofern zwischenzeitlich die Formulargröße verändert wurde (ist ja flüssig möglich, da die Bitmap-Berechnung in einem Thread läuft) passt der Inhalt nicht zur Formulargröße. Es gibt einen Rand oder es wird etwas abgeschnitten.
Es wird aber sofort eine Neuberechnung ausgelöst, so dass der Inhalt an die neue Größe angepasst wird. Man erhält also einen Nachlaufeffekt, bis die Bitmapgröße zur Formulargröße passt.
Flackern tut da aber nichts.
Stahli
http://www.StahliSoft.de
---
"Jetzt muss ich seh´n, dass ich kein Denkfehler mach...!?" Dittsche (2004)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#14

AW: Canvas: Änderungen/Bewegungen zeichnen

  Alt 1. Sep 2018, 16:12
man muss aber extra jedes Mal die Winapi verwenden.
Du kannst das aber auch einmal in einer Funktion kapseln und dann die statt der WinAPI verwenden
oder besser noch es per Class-Helper als dein eigenes LineToIrgendwas an TCanvas hängen.
$2B or not $2B
  Mit Zitat antworten Zitat
Jens01

Registriert seit: 14. Apr 2009
673 Beiträge
 
#15

AW: Canvas: Änderungen/Bewegungen zeichnen

  Alt 1. Sep 2018, 18:51
Zitat:
Das einzige, das ich etwas störend/umständlich finde, sind die runden Enden von Linien, die man mit der Methode LineTo auf die Bitmaps zeichnet.
Das hier solltest Du Dir angucken:
http://angusj.com/delphi/gr32_lines.php

Es ist zwar schon veraltet aber gut...
Achtung: Bin kein Informatiker sondern komme vom Bau.
  Mit Zitat antworten Zitat
Scurra

Registriert seit: 19. Jan 2015
81 Beiträge
 
Delphi 10.3 Rio
 
#16

AW: Canvas: Änderungen/Bewegungen zeichnen

  Alt 1. Sep 2018, 20:43
Zitat:
Sofern zwischenzeitlich die Formulargröße verändert wurde (ist ja flüssig möglich, da die Bitmap-Berechnung in einem Thread läuft) passt der Inhalt nicht zur Formulargröße. Es gibt einen Rand oder es wird etwas abgeschnitten.
Es wird aber sofort eine Neuberechnung ausgelöst, so dass der Inhalt an die neue Größe angepasst wird. Man erhält also einen Nachlaufeffekt, bis die Bitmapgröße zur Formulargröße passt.
Flackern tut da aber nichts.
Läuft wirklich sehr flüssig Den Nachlaufeffekt kann man zwar sehen, ist aber weniger schlimm, als ich erwartet hätte.

Zitat:
oder besser noch es per Class-Helper als dein eigenes LineToIrgendwas an TCanvas hängen.
Klingt nach einer guten Idee

Zitat:
Das hier solltest Du Dir angucken:
http://angusj.com/delphi/gr32_lines.php

Es ist zwar schon veraltet aber gut...
Wirklich interessant, dass es auch für solche Kleinigkeiten schon feritge Lösngen gibt. Ich werde es aber erst einmal bei der Lösung mit dem Class-Helper belassen. Hab ohnehin noch viel Arbeit vor mir.
  Mit Zitat antworten Zitat
Benutzerbild von KodeZwerg
KodeZwerg

Registriert seit: 1. Feb 2018
3.691 Beiträge
 
Delphi 11 Alexandria
 
#17

AW: Canvas: Änderungen/Bewegungen zeichnen

  Alt 1. Sep 2018, 21:22
Zeig doch mal ein Foto, würde mich interessieren was Du Dir da Programmierst. Klingt auf jeden Fall nach einem schönen Thema.
Gruß vom KodeZwerg
  Mit Zitat antworten Zitat
Scurra

Registriert seit: 19. Jan 2015
81 Beiträge
 
Delphi 10.3 Rio
 
#18

AW: Canvas: Änderungen/Bewegungen zeichnen

  Alt 1. Sep 2018, 22:05
Es gibt noch nicht wirklich viel zu sehen. Im Hauptformular (Anhang Main.jpg) ist bisher nur der nackte Aufbau des UIs zu erkennen. Über einen separaten Einstellungs-Dialog kann man Datum und Uhrzeit im Spiel und das Wetter einstellen. Letzteres ist im Moment noch statisch, d. h. es verändert sich noch nicht mit der Zeit. Die Anzeige der eingestellten Uhrzeit hat mich besonders viel Zeit gekostet, weil ich den Eindruck hatte, dass Timer ziemlich unpräzise sind und ich auch weitestgehend auf Timer verzichten möchte. Stattdessen habe ich eine Klasse implementiert, die mit Hilfe eines Threads nach jeder Sekunde einen Callback an den UI-Thread ausführt, damit dieser im UI die aktuelle Spielzeit anzeigen kann. Die Klasse bietet auch die Möglichkeit, den Thread zu pausieren (wenn man Spieleinstellungen ändert, soll die Simulation stehen bleiben, d. h. auch die Uhrzeit darf sich nicht ändern).

Ähnlich möchte ich das auch für das Aktualisieren des Radarbildschirms machen, die Implementierung ist ja schon vorhanden. Hier soll der Thread beispielsweise alle 2 Sekunden ein Event triggern, das meinem Programm sagt, dass der Radarbildschirm aktualisiert werden soll.

Im Anhang "Zeichnen.jpg" sind meine ersten Versuche beim Zeichnen, die ich im Rahmen dieses Themas im Forum gemacht habe. In der Demoanwendung habe ich einen Timer verwendet, um die Position der angezeigten Elemente jede Sekunde um 3 Pixel nach rechts wandern zu lassen (letzteres kann man im Screenshot natürlich nicht sehen ).
Miniaturansicht angehängter Grafiken
main.jpg   zeichnen.jpg  

Geändert von Scurra ( 1. Sep 2018 um 22:08 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von KodeZwerg
KodeZwerg

Registriert seit: 1. Feb 2018
3.691 Beiträge
 
Delphi 11 Alexandria
 
#19

AW: Canvas: Änderungen/Bewegungen zeichnen

  Alt 1. Sep 2018, 22:42
Scurra, Danke fürs Zeigen, nun hat man eine Ersteindruck woran Du werkelst auch visuell.
Dein "Flugzeug mit Label" Rohbau macht auch ne gute Figur (das zweite Bild).
Sieht vielversprechend aus, nur weiter so!
Gruß vom KodeZwerg
  Mit Zitat antworten Zitat
Scurra

Registriert seit: 19. Jan 2015
81 Beiträge
 
Delphi 10.3 Rio
 
#20

AW: Canvas: Änderungen/Bewegungen zeichnen

  Alt 25. Dez 2019, 11:16
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.
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 2 von 3     12 3      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 00:14 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz