AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Algorithmen, Datenstrukturen und Klassendesign Delphi Oberfläche wird nicht vollständig aktualisiert
Thema durchsuchen
Ansicht
Themen-Optionen

Oberfläche wird nicht vollständig aktualisiert

Ein Thema von knaeuel · begonnen am 16. Aug 2010 · letzter Beitrag vom 16. Aug 2010
Antwort Antwort
knaeuel

Registriert seit: 2. Jul 2007
110 Beiträge
 
Delphi 10.3 Rio
 
#1

Oberfläche wird nicht vollständig aktualisiert

  Alt 16. Aug 2010, 12:29
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?
Wolfgang

Geändert von knaeuel (16. Aug 2010 um 12:44 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Daniela.S
Daniela.S

Registriert seit: 1. Mär 2008
Ort: Niederösterreich
224 Beiträge
 
Delphi XE4 Enterprise
 
#2

AW: Oberfläche wird nicht vollständig aktualisiert

  Alt 16. Aug 2010, 12:54
Ein bisschen Source aus der Paint Procedure wäre hilfreich. Ansonsten bleibt nur raten... irgendwo beim Zeichnen falsches Handle erwischt?
  Mit Zitat antworten Zitat
knaeuel

Registriert seit: 2. Jul 2007
110 Beiträge
 
Delphi 10.3 Rio
 
#3

AW: Oberfläche wird nicht vollständig aktualisiert

  Alt 16. Aug 2010, 13:07
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;
Wolfgang

Geändert von knaeuel (16. Aug 2010 um 13:32 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Daniela.S
Daniela.S

Registriert seit: 1. Mär 2008
Ort: Niederösterreich
224 Beiträge
 
Delphi XE4 Enterprise
 
#4

AW: Oberfläche wird nicht vollständig aktualisiert

  Alt 16. Aug 2010, 13:43
Also ich würde mal Paint in den protected Bereich verschieben.

Delphi-Quellcode:
  protected
    { Protected-Deklarationen }
    procedure Paint; override;
Inherited ist eigentlich nicht notwendig, da du, wenn du den Hintergrund löscht, nichts aus der Originalroutine benötigst.
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;
  Mit Zitat antworten Zitat
knaeuel

Registriert seit: 2. Jul 2007
110 Beiträge
 
Delphi 10.3 Rio
 
#5

AW: Oberfläche wird nicht vollständig aktualisiert

  Alt 16. Aug 2010, 14:06
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
Wolfgang
  Mit Zitat antworten Zitat
Benutzerbild von fkerber
fkerber
(CodeLib-Manager)

Registriert seit: 9. Jul 2003
Ort: Ensdorf
6.723 Beiträge
 
Delphi XE Professional
 
#6

AW: Oberfläche wird nicht vollständig aktualisiert

  Alt 16. Aug 2010, 14:10
Hi!

Delphi-Referenz durchsuchenBitBlt mit t am Ende


Liebe Grüße,
Frederic
Frederic Kerber
  Mit Zitat antworten Zitat
knaeuel

Registriert seit: 2. Jul 2007
110 Beiträge
 
Delphi 10.3 Rio
 
#7

AW: Oberfläche wird nicht vollständig aktualisiert

  Alt 16. Aug 2010, 14:27
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
Wolfgang
  Mit Zitat antworten Zitat
Benutzerbild von Bummi
Bummi

Registriert seit: 15. Jun 2010
Ort: Augsburg Bayern Süddeutschland
3.470 Beiträge
 
Delphi XE3 Enterprise
 
#8

AW: Oberfläche wird nicht vollständig aktualisiert

  Alt 16. Aug 2010, 14:31
leite doch von TGraphiccontrol ab ....
Thomas Wassermann H₂♂
Das Problem steckt meistens zwischen den Ohren
DRY DRY KISS
H₂ (wenn bei meinen Snipplets nichts anderes angegeben ist Lizenz: WTFPL)
  Mit Zitat antworten Zitat
Benutzerbild von SirThornberry
SirThornberry
(Moderator)

Registriert seit: 23. Sep 2003
Ort: Bockwen
12.235 Beiträge
 
Delphi 2006 Professional
 
#9

AW: Oberfläche wird nicht vollständig aktualisiert

  Alt 16. Aug 2010, 16:28
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.
Jens
Mit Source ist es wie mit Kunst - Hauptsache der Künstler versteht's

Geändert von SirThornberry (16. Aug 2010 um 16:30 Uhr)
  Mit Zitat antworten Zitat
Antwort Antwort


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 01:09 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