Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Lazarus (IDE) (https://www.delphipraxis.net/81-lazarus-ide/)
-   -   -fixed- Panel überladen und anzeigen (https://www.delphipraxis.net/172030-fixed-panel-ueberladen-und-anzeigen.html)

Highttower 9. Dez 2012 17:21


-fixed- Panel überladen und anzeigen
 
Hallo zusammen,

ich sitze gerade zusammen mit meiner Schwester vor einem kleinen Problemchen in Lazaerus.

Aufgaben beschreibung sind mal wieder die berühmten Türme von Hanoi, dieses gilt es allerdings grafisch Darzustellen.

Mein Ansatz sieht wie folgt aus:

Eine Klasse für die Logik der Türme und deren Stack.
Eine Klasse die alle drei Türme als Einheit zusammenfügt und die "Logik" der Scheiben beinhaltet.

Soweit funktioniert auch alles, jetzt geht es daran die Sache Grafisch darzustellen:

Dazu habe ich eine Klasse von TPanel abgeleitet die ich jetzt immer mit neuen Panels als Scheiben befüllen will. Das müsste mit den Anchors recht gut funktionieren:

Delphi-Quellcode:
uses
  Classes, SysUtils, uBTuerme, Forms, Controls, Graphics, Dialogs, ExtCtrls,
  StdCtrls;

type

  { TVisTower }

  TVisTower = class(TPanel)
  strict private
  private
    // std. verstecken ...
    constructor Create(AOwner: TComponent); override;
  protected
    procedure MaleTurm(ATower: TTower);
  public
    constructor Create(AOwner: TComponent; ATower: TTower; ALeft, ATop, AWidth : Integer);
  published

  end;

implementation

{ TVisTower }

constructor TVisTower.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
end;

procedure TVisTower.MaleTurm(ATower: TTower);
var
  schicht: TPanel;
  i: integer;
begin

  i := 1;

  if (not ATower.IsEmpty) then
  begin
    repeat
      schicht := TPanel.Create(self);
      schicht.Anchors := [akBottom];
      schicht.Width := self.Width - (i * 4);
      schicht.Left := 2;
      if ((i mod 2) = 0) then
         schicht.Color := clRed
      else
         schicht.Color := clGreen;
      schicht.Caption:= IntToStr(ATower.Get);
      inc(i);
    until ATower.IsEmpty;
  end;
end;

constructor TVisTower.Create(AOwner: TComponent; ATower: TTower; ALeft, ATop, AWidth : Integer);
begin
  inherited Create(AOwner);
  self.Width:= AWidth;
  self.Top:= ATop;
  self.Left:= ALeft;
  MaleTurm(ATower);
end;
Wenn ich das teil jetzt mit einem Turm (

Delphi-Quellcode:
uses
  Classes, SysUtils;

type

  TEnumTuerme = (Turm1, Turm2, Turm3);



  { TTower }

  TTower = class
  private
    Items: array of integer;
  protected
     function IsItEmpty: boolean;
  public
    procedure Add(AItem: integer);
    function Get: integer;
    function Copy: TTower;

    property IsEmpty : boolean read IsItEmpty;
  end;

implementation

{ TTower }

procedure TTower.Add(AItem: integer);
begin
  if (IsEmpty) or (AItem < Items[Length(Items) - 1]) then
  begin
    SetLength(Items, Length(Items) + 1);
    Items[Length(Items) - 1] := AItem;
  end
  else
    raise Exception.Create('Platte ist zu groß!');
end;

function TTower.Get: integer;
begin
  if (not IsEmpty) then
  begin
    Result := Items[Length(Items) - 1];

    // letztes löschen
    SetLength(Items, Length(Items) - 1);
  end
  else
    raise EOutOfResources.Create('Tower stack is empty!');
end;

function TTower.IsItEmpty: boolean;
begin
  Result := (Length(Items) = 0);
end;

function TTower.Copy: TTower;
var
  i: integer;
begin
  Result := TTower.Create;

  for i in Items do
    Result.Add(i);

end;
Lade läuf auch alles ohne Fehler durch ... allerdings bekomme ich das Panel nicht auf das Formular:

Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var Hanoi : THanio;
begin
Hanoi := THanio.Create(5);
   // AOwner: TComponent; ATower: TTower; ALeft, ATop, AWidth : Integer
   FTurm1 := TVisTower.Create(self, Hanoi.Turm1, 0, 420,200); ;

   FTurm1.Repaint();

   self.Repaint;  
end;
Muss ich noch irgendwas wichtiges neu zeichnen? Irgendwo nen Handle übergeben oder habe ich an irgendeiner Stelle etwas wichtiges vergessen?

Vielen Dank für eure Ratschläge,

Tobi


EDIT:
Fixed :D
Delphi-Quellcode:
 FTurm1.Parent := self;

sx2008 10. Dez 2012 02:26

AW: -fixed- Panel überladen und anzeigen
 
Zitat:

Zitat von Highttower (Beitrag 1194861)
Soweit funktioniert auch alles, jetzt geht es daran die Sache Grafisch darzustellen:
Dazu habe ich eine Klasse von TPanel abgeleitet die ich jetzt immer mit neuen Panels als Scheiben befüllen will.

Warum leitest du von einem Panel ab?
Das ist doch unflexibel und umständlich.

Stattdessen nimmt man eine ganz normale Klasse:
Delphi-Quellcode:
  TVisTower = class(TObject)
  private
    FContainer : TWinControl;

  protected
    procedure MaleTurm(ATower: TTower);
  public
    constructor Create(AContainer:TWinControl);
  published

  end;
und übergibt einen "Container".
Das könnte ein Panel, eine Groupbox oder ein Formular sein.
Kurz gesagt, jedes Control, dass andere Controls aufnehmen kann ist als Basis geeignet.
Auf diesem Container werden nun die farbigen Panels, die die Scheiben darstellen erzeugt.
Delphi-Quellcode:
  while not ATower.IsEmpty do
  begin
    schicht := TPanel.Create(FContainer);
    schicht.Anchors := [akBottom];
    schicht.Width := FContainer.Width - (i * 4);
    schicht.Left := 2;
    schicht.Height := 10;
    schicht.Top := i * schicht.Height;
    if ((i mod 2) = 0) then
       schicht.Color := clRed
    else
       schicht.Color := clGreen;

    schicht.Caption:= IntToStr(ATower.Get);
    // Diese Zuweisung macht das neu erzeugte Panel erst sichtbar!
    schicht.Parent := FContainer;
    inc(i);
  end;


Alle Zeitangaben in WEZ +1. Es ist jetzt 16:32 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