![]() |
Oberfläche wird nicht vollständig aktualisiert
Hallo liebes Forum,
folgendes Problem: ich habe eine eigene Komponente TMyImage erstellt, abgeleitet von TImage. Wenn ich nun meine neue Komponente benutze, dann werden nicht mehr alle Objekte der Oberfläche aktualisiert. TLabeledEdit, TButton, ... die hängen alle fest. Soweit ich das gerade sehe, wird die Oberfläche nur noch vollständig aktualisiert, wenn ich das Fenster verschiebe oder die Größe des Fensters ändere. Die Felder werden außerdem noch aktualisiert, wenn ich direkt drauf-/reinklicke. Minimieren, Maximieren, Wertänderungen bei den Editfeldern haben keinen Effekt. TMyImage hat eine eigene Paint-Methode, deklariert als published procedure Paint(); override; In der Implementierung rufe ich zunächst inherited; auf, anschließend werden aus einem Array zu zeichnende Objekte gelesen und gezeichnet. Die Klasse TMyImage stellt außerdem die beiden Events MouseDown und MouseMove zur Verfügung. Beide Procedures sind als reiner Aufruf von inherited; implementiert. Kann mir jemand verraten, womit ich die Aktualisierung der Oberfläche platt gemacht habe? |
AW: Oberfläche wird nicht vollständig aktualisiert
Ein bisschen Source aus der Paint Procedure wäre hilfreich. Ansonsten bleibt nur raten... irgendwo beim Zeichnen falsches Handle erwischt?
|
AW: Oberfläche wird nicht vollständig aktualisiert
hier die Paint-Methode. Leider ist sie etwas länger. Kurz zusammengefasst malt sie die Akteure auf einem großem gedachten Kreis und zeichnet anschließend Verbindungslinien, wenn welche definiert wurden.
Code:
procedure TSozioImage.Paint();
var ai:integer; a,b,c:real; act_color:TColor; bi,wert:integer; ckurz,akurz,bkurz,steigung,xziel,yziel:real; begin //zuerst: inherited; //alle Akteure einzeichnen Picture.Bitmap.Canvas.Pen.Color:=initial_pen_color; Picture.Bitmap.Canvas.Brush.Color:=clWhite;//initial_brush_color; for ai := 0 to anzahl_akteure-1 do begin act_color:=akteur[ai].color; Picture.Bitmap.Canvas.Pen.Color:=act_color; KreisZeichnen(akteur[ai].x,akteur[ai].y,akteur[ai].radius,true,act_color); Picture.Bitmap.Canvas.Font.Color:=act_color; Picture.Bitmap.Canvas.TextOut(wc.vx2x(akteur[ai].bx),wc.vy2y(akteur[ai].by),akteur[ai].akteur); end; //alle Verbindungen einzeichnen for ai:=0 to length(akteur)-1 do begin Picture.Bitmap.Canvas.Pen.Color:=akteur[ai].color; for bi:=0 to length(akteur[ai].output)-1 do begin if ai<>bi then //Beziehung zu sich selbst überspringen begin //eine Beziehung einlesen wert:=StrToInt(akteur[ai].output[bi]); //zeichnen if wert>0 then begin Picture.Bitmap.Canvas.MoveTo(wc.vx2x(akteur[ai].x),wc.vy2y(akteur[ai].y)); //Endpunkt der Linie berechnen: //die Linie soll bereits bei Erreichen des Kreises des Ziels enden //und eine Pfeilspitze erhalten //1. Länge der Verbindungsgeraden bestimmen (Hypotenuse c) a:=(akteur[bi].x-akteur[ai].x); b:=(akteur[bi].y-akteur[ai].y); c:=sqrt(a*a+b*b); //c um den Radius des Ziel"kreises" verkürzen ckurz:=c-akteur[bi].radius; //2. neues verkürztes Steigungsdreieck berechnen //Steigung der Hypotenuse ist konstant steigung:=b/a; //neues a: a²+(a*steigung)²=c² akurz:=sqrt(ckurz*ckurz/(steigung*steigung+1)); //neues b: a²+b²=c² bkurz:=sqrt(ckurz*ckurz-akurz*akurz); //3. Koordinaten bestimmen //a>=0: nach oben zeichnen //a<0: nach unten zeichnen if a>=0 then xziel:=akteur[ai].x+akurz else xziel:=akteur[ai].x-akurz; //b>=0: nach rechts zeichnen //b<0: nach links zeichnen if b>=0 then yziel:=akteur[ai].y+bkurz else yziel:=akteur[ai].y-bkurz; Picture.Bitmap.Canvas.LineTo(wc.vx2x(xziel),wc.vy2y(yziel)); end; end; end; end; //am Ende // inherited; end; |
AW: Oberfläche wird nicht vollständig aktualisiert
Also ich würde mal Paint in den protected Bereich verschieben.
Delphi-Quellcode:
Inherited ist eigentlich nicht notwendig, da du, wenn du den Hintergrund löscht, nichts aus der Originalroutine benötigst.
protected
{ Protected-Deklarationen } procedure Paint; override; Besser wäre es in eine temporäre Bitmap zu zeichnen und dann mit BitBlt auf einmal zu veröffentlichen. Das minimiert auch lästiges Flackern.
Delphi-Quellcode:
procedure TMyImage.Paint();
var bmp : TBitmap; begin // temporäres Bitmap erstellen bmp := TBitmap.Create; try // Größe festlegen bmp.Width := Self.Width; bmp.Height := Self.Height; // Hintergrund weiss färben with bmp.Canvas do begin Brush.Color := clWhite; Brush.Style := bsSolid; FillRect( Rect( 0, 0, bmp.Width, bmp.Height ) ); end; // jetzt alles in bmp.Canvas zeichnen // zum Abschluss auf den richtigen Canvas zeichnen BitBlt( Self.Canvas.Handle, 0, 0, Self.Width, Self.Height, bmp.Canvas.Handle, 0, 0, SRCCOPY ); finally FreeAndNil( bmp ); end; end; |
AW: Oberfläche wird nicht vollständig aktualisiert
wenn ich den inherited-Aufruf entferne, wird die Grafik gar nicht mehr gezeichnet. Die restliche Oberfläche wird allerdings aktualisiert.
Den Befehl BitBlp gibt es bei Delphi 2006 scheinbar nicht. Ich suche gerade nach Alternativen. Es sieht wohl nach CopyRect oder so ähnlich aus. Ergebnis kommt in Kürze |
AW: Oberfläche wird nicht vollständig aktualisiert
|
AW: Oberfläche wird nicht vollständig aktualisiert
ah danke, ja, ich hab das jetzt genau so umgesetzt.
Ohne inherited-Aufruf wird tatsächlich nichts von der Grafik angezeigt. Was mir bisher gar nicht aufgefallen war: sobald die Paint-Methode Daten zum Anzeigen findet, braucht das Programm eine CPU komplett für sich. Daher dann wohl auch die fehlenden Aktualisierungen. Die Frage ist also jetzt, warum hört das Programm nicht auf, die Paint-Methode aufzurufen. und siehe da, da hatte ich noch in der Procedure KreisZeichnen einen direkten Zugriff auf Canvas. Den noch entfernt und das temporäre Bitmap in KreisZeichnen rübergereicht und mitbenutzt. Jetzt ist die CPU-Last wech, die Paint-Methode wird nur noch aufgerufen, wenns wirklich nötig ist. OK, also ich bin schon überrascht, dass ich das Canvas-Objekt nicht einfach nach Gusto benutzen darf. Herzlichen Dank für die Hilfe und die gleich mitgereichte Implementierung des Double Buffers :-) |
AW: Oberfläche wird nicht vollständig aktualisiert
leite doch von TGraphiccontrol ab ....
|
AW: Oberfläche wird nicht vollständig aktualisiert
Das Problem ist recht einfach beschrieben. So bald Picture von TImage geändert wird, wird dafür gesorgt das dies auch sichtbar wird. Und dies geschieht über einige Zwischenaufrufe durch den Aufruf von Paint. Im Paint änderst du jedoch wieder den Inhalt von dem was TImage anzeigen soll und somit wird erneut das Paint aufgerufen. Und das setzt sich immer so fort.
@knaeuel: Verwende zukünftig bitte die delphi-Tags anstelle der Code-Tags wenn du Delphi-Code postest. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 23:36 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz