AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein GUI-Design mit VCL / FireMonkey / Common Controls Delphi Anwendung ruckelt beim Vergrößern/Verkleinern

Anwendung ruckelt beim Vergrößern/Verkleinern

Ein Thema von Aviator · begonnen am 25. Jun 2016 · letzter Beitrag vom 26. Jun 2016
Antwort Antwort
Aviator

Registriert seit: 3. Jun 2010
1.610 Beiträge
 
Delphi 10.3 Rio
 
#1

Anwendung ruckelt beim Vergrößern/Verkleinern

  Alt 25. Jun 2016, 19:11
Hallo zusammen,

mit folgendem Quellcode zeichne ich diverse Bilder in eine PaintBox:

Delphi-Quellcode:
procedure TfrmCardInfo.pbCardsPaint(Sender: TObject);
var
  i, col, row: Integer;
  BasePath, s: string;
  img: TJPEGImage;
  Start: Cardinal;
begin
  if (FBFCardInfoList.Count > 0) then begin
    img := TJPEGImage.Create;
    try
      col := 1;
      row := 0;
      i := 0;
      Start := GetTickCount;
      repeat
        FBFCardInfoList[i].Picture.Position := 0;
        img.LoadFromStream(FBFCardInfoList[i].Picture);
        pbCards.Canvas.Draw((col - 1) * img.Width + 5, row * img.Height + 10, img);

        if ((col mod FMaxCols) = 0) then begin
          col := 1;
          Inc(row);
        end else
          Inc(col);
        Inc(i);
      until (i >= FBFCardInfoList.Count);
      lblOrbs.Caption := IntToStr((GetTickCount - Start));
    finally
      img.Free;
    end;
  end;
end;
Die Bilder wurden zuvor in einem Thread von der Festplatte geladen und werden nun in einem Klassenobjekt in einer Objectlist aufbewahrt. Ich lade beim Zeichnen der Bilder auch immer nur noch aus einem Stream in ein TJPEGImage. Jedoch fängt die Anwendung an zu ruckeln, sobald ich das Fenster vergrößere und verkleinere. Die PaintBox in die gezeichnet wird, wird beim ändern der Formgröße immer durch die Anchor Property mit angepasst. Nehme ich die Zeile pbCards.Canvas.Draw((col - 1) * img.Width + 5, row * img.Height + 10, img); raus, dann läuft es flüssig(er). Getestet unter Windows 10 und Windows 7. Woran kann das liegen? Ist die Canvas.Draw Methode wirklich so langsam?

Wie kann ich das beschleunigen, da ich diese Ruckeleffekte nicht haben möchte?

PS: Das lblOrbs habe ich dazu verwendet, um die Zeit auszugeben wie lange gezeichnet wird. Das Ergebnis liegt immer irgendwo bei 300 - 370ms.

Geändert von Aviator (25. Jun 2016 um 20:34 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Zacherl
Zacherl

Registriert seit: 3. Sep 2004
4.629 Beiträge
 
Delphi 10.2 Tokyo Starter
 
#2

AW: Anwendung ruckelt beim Vergrößern/Verkleinern

  Alt 25. Jun 2016, 20:05
Was passiert, wenn du deine Grafiken zuerst auf ein internes Buffer Bitmap zeichnest und dann nur einmalig das Bitmap in der Paintbox ausgibst? Zudem könntest du schauen, ob die geänderte Größe im Vergleich zur letzten Größe überhaupt mehr Cols und Rows anzeigen kann. Falls nicht, nimmst du einfach wieder das alte Bitmap und sparst dir das interne Zeichnen komplett.
Projekte:
- GitHub (Profil, zyantific)
- zYan Disassembler Engine ( Zydis Online, Zydis GitHub)
  Mit Zitat antworten Zitat
Aviator

Registriert seit: 3. Jun 2010
1.610 Beiträge
 
Delphi 10.3 Rio
 
#3

AW: Anwendung ruckelt beim Vergrößern/Verkleinern

  Alt 26. Jun 2016, 00:21
Was passiert, wenn du deine Grafiken zuerst auf ein internes Buffer Bitmap zeichnest und dann nur einmalig das Bitmap in der Paintbox ausgibst? Zudem könntest du schauen, ob die geänderte Größe im Vergleich zur letzten Größe überhaupt mehr Cols und Rows anzeigen kann. Falls nicht, nimmst du einfach wieder das alte Bitmap und sparst dir das interne Zeichnen komplett.
Hi Zacherl,
das werde ich mal ausprobieren. Bin auch schon relativ weit gekommen, aber es funkioniert noch nicht ganz. Werde aber dementsprechend Rückmeldung geben wie und ob es (besser) funktioniert. Schonmal danke für den Tipp.
  Mit Zitat antworten Zitat
Aviator

Registriert seit: 3. Jun 2010
1.610 Beiträge
 
Delphi 10.3 Rio
 
#4

AW: Anwendung ruckelt beim Vergrößern/Verkleinern

  Alt 26. Jun 2016, 01:10
Hallo zusammen,

habe es jetzt doch noch geschafft, dass auszuprobieren. Das interne Bild wird gemalt und dann erst mit PaintBox.Canvas.Draw(0, 0, InternalBmp); auf die Paintbox gemalt. Beim Vergrößern und Verkleinern der Form wird nur noch neu gezeichnet, wenn sich wirklich die Anzahl der Spalten (und u. U. dadurch auch die Anzahl der Zeilen) verändert. Solange sich die Anzahl Spalten nicht verändert, lässt sich die Form weitestgehend normal ohne ruckeln vergrößern bzw. verkleinern. Sobald aber nachgerechnet und auch neu gezeichnet wird, fängt das Spiel wieder von vorne an. Ich habe jetzt mal 60 Bilder geladen und das aufbauen bzw. neuzeichnen geht schon fast in den Sekundenbereich.

Woran kann das liegen? Ich bin für jeden Tipp dankbar.

Anbei mal noch die relevanten Zeilen, in denen ich das Bild aktuell male:

(Das ständige neu setzen der Größe des InternalBitmap hat übrigens keinen negativen Effekt auf die Dauer. Habe es testweise an eine andere Stelle verschoben und es hat sich nichts geändert.

Delphi-Quellcode:
procedure TfrmCardInfo.GetMaximumColumnsAndRows(const APaintBoxWidth: Integer);
const
  SPACE = 10;
var
  img: TJPEGImage;
  s: string;
begin
  try
    img := TJPEGImage.Create;
    try
      FBFCardInfoList[0].Picture.Position := 0;
      img.LoadFromStream(FBFCardInfoList[0].Picture);
      MaxCols := APaintBoxWidth div (img.Width + SPACE);
      MaxRows := Ceil(FBFCardInfoList.Count / MaxCols);
      PaintBoxHeight := MaxRows * (img.Height + SPACE);
      FInternalBitmap.Height := pbCards.Height;
      FInternalBitmap.Width := pbCards.Width;
    finally
      img.Free;
    end;
  except
    //
  end;
end;

procedure TfrmCardInfo.pbCardsPaint(Sender: TObject);
begin
  pbCards.Canvas.Draw(0, 0, FInternalBitmap);
end;

procedure TfrmCardInfo.RepaintInternalBitmap;
var
  i, col, row, xPos, yPos: Integer;
  img: TJPEGImage;
begin
  FInternalBitmap.Canvas.Brush.Color := clBlack;
  FInternalBitmap.Canvas.FillRect(FInternalBitmap.Canvas.ClipRect);

  Inc(Repaints);
  lblOrbs.Caption := IntToStr(Repaints);
  img := TJPEGImage.Create;
  try
    col := 1;
    row := 0;
    i := 0;
    repeat
      FBFCardInfoList[i].Picture.Position := 0;
      img.LoadFromStream(FBFCardInfoList[i].Picture);
      xPos := (col - 1) * img.Width + 5;
      yPos := row * img.Height + 10;
      FInternalBitmap.Canvas.Draw(xPos, yPos, img);

      if ((col mod FMaxCols) = 0) then begin
        col := 1;
        Inc(row);
      end else
        Inc(col);
      Inc(i);
    until (i >= FBFCardInfoList.Count);
  finally
    img.Free;
  end;
end;

procedure TfrmCardInfo.scbCardsResize(Sender: TObject);
begin
  GetMaximumColumnsAndRows(pbCards.Width);
end;

procedure TfrmCardInfo.SetMaxCols(const Value: Integer);
begin
  if (MaxCols <> Value) then begin
    FMaxCols := Value;
    RepaintInternalBitmap; // InternalBitmap has to be drawn only once because the maximum number of rows depends on the number of columns
  end;
end;

procedure TfrmCardInfo.SetMaxRows(const Value: Integer);
begin
  if (FMaxRows <> Value) then begin
    FMaxRows := Value;
  end;
end;

procedure TfrmCardInfo.SetPaintBoxHeight(const Value: Integer);
begin
  if (FPaintBoxHeight <> Value) then begin
    FPaintBoxHeight := Value;
    pbCards.Height := Value;
  end;
end;
  Mit Zitat antworten Zitat
Benutzerbild von Luckie
Luckie

Registriert seit: 29. Mai 2002
37.621 Beiträge
 
Delphi 2006 Professional
 
#5

AW: Anwendung ruckelt beim Vergrößern/Verkleinern

  Alt 26. Jun 2016, 02:32
Ich glaube BitBlt ist performanter.
Michael
Ein Teil meines Codes würde euch verunsichern.
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#6

AW: Anwendung ruckelt beim Vergrößern/Verkleinern

  Alt 26. Jun 2016, 03:34
Das ständige Laden eines JPEG aus dem Stream in GetMaximumColumnsAndRows kann man sich durch das Cachen der Werte (die werden sich zur Laufzeit nicht mehr verändern) schenken. Einmal reicht.

Das ständige Laden der Grafiken als JPEG ist auch langsamer, als wenn man sich die Bilder beim ersten Zugriff als Bitmap merkt und dann immer dieses gecachte Bitmap verwendet.

Erstelle dir ein Surrogate (Stellvertreter) für die Bilder. Der Konstruktor erhält z.B. den Dateinamen. Beim ersten Zugriff wird das Bild aus der datei geladen und intern als Bitmap gespeichert. Danach erfolgt jeder weitere Zugriff direkt auf das Bitmap.

Den Surrogate leitet man von TPersistent ab und überschreibt die virtuelle Methode AssignTo .

Zum Zeichnen braucht es dann nur noch
Delphi-Quellcode:
img := TBitmap.Create;

img.Assign( Surrogates[i] ); // temp. Bitmap mit dem Surrogate füllen
// Zeichnen von img
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
Aviator

Registriert seit: 3. Jun 2010
1.610 Beiträge
 
Delphi 10.3 Rio
 
#7

AW: Anwendung ruckelt beim Vergrößern/Verkleinern

  Alt 26. Jun 2016, 14:49
Hallo Sir Rufo,

ich habe das mal so probiert wie du es gesagt hast. Ich hoffe mal, dass ich das richtig umgesetzt habe. Aber es ist auf jeden Fall schonmal ein gutes Stück schneller und bei normaler FullHD Auflösung ruckelt es auch eigentlich nicht mehr. Bei 4K allerdings merkt man es doch noch etwas. Wobei 4K ja eigentlich nicht so verbreitet ist und das Programm jetzt auch nicht zwingend darauf absolut perfekt laufen muss.

Danke für den Hinweis.

Und danke auch an @Lucky. Das werde ich mir mal ansehen. Kann man damit auch Grafiken verkleinert zeichnen wie man das mit StretchDraw machen kann
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#8

AW: Anwendung ruckelt beim Vergrößern/Verkleinern

  Alt 26. Jun 2016, 15:16
Du musst ja auch nicht jeden Vergrößerungsschritt mitmachen. Wenn du auf die Vergrößerung asynchron reagierst (z.B. per Timer mit Intervall 100/250 -> ausprobieren) dann sollte das auch reichen.
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
EWeiss
(Gast)

n/a Beiträge
 
#9

AW: Anwendung ruckelt beim Vergrößern/Verkleinern

  Alt 26. Jun 2016, 17:16
Zitat:
Kann man damit auch Grafiken verkleinert zeichnen wie man das mit StretchDraw machen kann
Das Äquivalent für StretchDraw wäre dann StretchBlt.

BitBlt zum Kopieren.
StretchBlt zum verändern.

gruss
  Mit Zitat antworten Zitat
Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

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 15:27 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