Autor Beitrag
Martok
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 3661
Erhaltene Danke: 604

Win 8.1, Win 10 x64
Pascal: Lazarus Snapshot, Delphi 7,2007; PHP, JS: WebStorm
BeitragVerfasst: Do 21.01.10 13:42 
Hallo,

in letzter Zeit kamen doch immer mal wieder Leute, die gerne was animiertes zeichnen möchten ( = Spiele).

Da habe ich oft den Tipp gelesen, man soll kein Canvas direkt benutzen, sondern eine Paintbox. Auch TImage als selbst-buffernde Ausgabemöglichkeit zu missbrauchen, wird kategorisch abgelehnt.
Da ich aber sowas oft brauche und alle 3 Varianten schon gemacht hab, kann ich das nicht wirklich nachvollziehen, wer das in die Welt gesetzt hat. Ich möchte daher mal eine Grundsatzdiskussion anleiern.
Sollte das in der Sparte nicht erwünscht sein, bitte ich um Verschiebung ins Off-Topic.
Je nach Resonanz kann hier durchaus mal ein Library-Artikel draus werden, wo die hier beschrieben Sachen mal etwas ausprobiert werden.

Also, ab ins Thema:
TImage geht nicht, weil wegen ist so.
Das konnte noch nie wer begründen... ob ich nun ein TBitmap selber halte, und das im Paint-Ereignis auf ein Canvas kopiere, oder ob das ein TImage macht, spielt genau keine Rolle. Das einzige Problem: es ist vielleicht etwas konterintuitiv, Dass man Image.Picture.Bitmap.Width/Height setzen muss. Ob das zu viel verlangt ist, muss jeder selber wissen. Mir persönlich ist das alle male lieber, als mich um den ganzen Rest kümmern zu müssen.
Gegen die Schreibarbeit kann man auch was tun:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
var B: TBitmap;
begin
  B:= Image1.Picture.Bitmap;
  b.width:= 42;
  b.Height:= 23;
  b.Canvas.Rect(...)


Ein TPanel/TForm/... kann man nicht nutzen, weil da kein Canvas da ist.
Außerdem fehlt das OnPaint.
Äh, nein. Es ist nur keins von beiden Public/Published. Und das stört nicht, weil man das wenn dann eh richtig macht. Wann würde man den diesen Ansatz nutzen? Richtig, wenn man z.B. eine Karte darstellen will. Da hat man dann normalerweise auch Interaktion, also brauche ich die Mausereignisse eh. Und da das hier Objektorientierte Programmierung ist, schreibt man sich da eh eine Klasse für.
Selbige leitet man von TCustomControl ab, und schon ist alles da. Procedure Paint überschreiben, fertig. Da kann man dann gleich DoubleBuffered setzen, und schon hat sich das Geflacker.
Und am Rande: Ratet mal, wo TPanel herkommt? Richtig, TCustomControl.
Das kann man ausnutzen:
ausblenden Delphi-Quelltext
1:
2:
3:
type
  TMyPanel = class(TPanel)
  end;

ausblenden Delphi-Quelltext
1:
TMyPanel(Panel1).Canvas.Rectangle(...);					

Gut, da hab ich kein OnPaint. Ich würde aber eh den ersten Weg nutzen, das hier ist nur ein Hack, wenn man mal unbedingt ein Canvas braucht.

TPaintbox ist das einzig Wahre.
Dass das nicht so ist, habe ich ja nun schon gezeigt.
Bliebe zu beweisen, dass TPaintbox auch eine der denkbar schlechtesten Möglichkeiten ist.
Schlagendes Argument dürfte wohl der mindestens 3 mal höhere Verwaltungsaufwand sein: eine TPaintbox muss man entweder auch ableiten, oder Ereignisse verdrahten. Dann braucht man ein eigenes Backbuffer-TBitmap. Und zu guter letzt muss irgendwer in dem passenden WinControl noch DoubleBuffering anschalten, damit man das einigermaßen genießen kann.

Außerhalb der Wertung: TForm
Hey, man kann auch auf der TForm selbst rum malen. OnPaint, Canvas: alles da.

Fazit:
TImage hat einen Nachteil: DoubleBuffered muss man manuell setzen.
TCustomControl hat auch einen: man muss den BackBuffer selbst verwalten.
TPaintbox hat beide.

Wo genau ist jetzt der Vorteil, letztere zu verwenden? Wer hat das verbreitet, dass die die optimale Wahl ist?

So, und jetzt bitte einen Religionskrieg :P

cu,
Martok

_________________
"The phoenix's price isn't inevitable. It's not part of some deep balance built into the universe. It's just the parts of the game where you haven't figured out yet how to cheat."
BenBE
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 8721
Erhaltene Danke: 191

Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
BeitragVerfasst: Do 21.01.10 14:45 
Also: Zu TImage ...
Sollte man vermeiden, da der Aufwand für dynamisches Neuzeichnen durch die X-fach-Pufferung i.d.R. die Performance beeinträchtigt. Für langsame Animationen mag es gehen, aber schnell ist was anderes ...

TForm hat ein Canvas direkt veröffentlicht. Sehe da nicht das Problem. Bei TPanel genauso (IIRC, ansonsten holt man sich das halt mit GetDC(Panel.Handle)). Sowohl TForm als auch TPanel sind durchaus möglich, da es sich aber jeweils um Container-Komponenten handelt, fängt man sich schnell Probleme ein, dass bestimmte Bereiche von Child-Controls überzeichnet werden. DAS nenn ich Kontraintuitiv ;-) Rein von der Performance aber, hat man bei beiden Varianten durchaus kaum Probleme; bei GetDC hat man ja eh das Canvas direkt unter seiner Kralle.

Das TPaintbox nun das einzig Wahre ist, sei mal dahingestellt. Denn trotzdem man ein Canvas und eine Reihe von Ereignissen hat, ist gerade das Handling dieser für den Einstieg nicht gerade hilfreich. Auch das partielle Neuzeichnen kann einem wenn man's nicht weiß durchaus Kopfschmerzen bereiten.

Ich bin ja eh dafür, sich auf nem beliebiegen HWND nen HDC zu holen und dazu den passenden HGLRC zu allokieren. Aber das ist ne andere Geschichte ;-) Zeichnen geht dann auf jeden Fall extrem schnell; und nicht so steinzeitlich wie bei TCanvas, was bei jedem Aufruf erstmal sämtliche(!!!) Resourcen von Windows neu anfordert.

_________________
Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
Tilman
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 1405
Erhaltene Danke: 51

Win 7, Android
Turbo Delphi, Eclipse
BeitragVerfasst: Do 21.01.10 14:57 
Zitat:
eine TPaintbox muss man entweder auch ableiten, oder Ereignisse verdrahten. Dann braucht man ein eigenes Backbuffer-TBitmap. Und zu guter letzt muss irgendwer in dem passenden WinControl noch DoubleBuffering anschalten, damit man das einigermaßen genießen kann.


Wozu muss man ne TPaintBox ableiten? Und DoubleBuffering hab ich eigentlich noch nie angestellt, wenn man nur in sein Bitmap malt und das dann ausgibt flackert da eigentlich nix.

Ansonsten einfach Geschmackssache würde ich sagen, aber wie BenBE schon sagte hab ich auch in Erinnerung dass TImage recht langsam werden kann.

Der Vorteil von TPaintBox gegenüber TForm besteht darin dass man die Paintbox frei positionieren kann, man bleibt damit flexibler.

_________________
Bringe einen Menschen zum grübeln, dann kannst du heimlich seinen Reis essen.
(Koreanisches Sprichwort)