Klasse soll VCL Kompenten erzeugen Man sieht nichts

Für Fragen von Einsteigern und Programmieranfängern...
Antworten
klausi1305
Beiträge: 35
Registriert: Mo 1. Jul 2013, 21:30
OS, Lazarus, FPC: Win 7 Laz 1.0.10
CPU-Target: 32 Bit
Wohnort: Leipzig

Klasse soll VCL Kompenten erzeugen Man sieht nichts

Beitrag von klausi1305 »

Hallo,
ich will eine Klasse erstellen, welche VCL Komponenten verwendent.
Speziell will ich im Create eine Scrollbox als Container, welche 2 Images übereinander beinhaltet erstellen.
Ich scheitere jedoch daran, das ich zwar was "erzeuge", jedoch sehe ich nichts auf der Form......

hier die Klasse

Code: Alles auswählen

Type
 
  { TSpielfeld }
 
  TSpielfeld = Class(TObject)
    protected
       MyScrollbox           : TScrollbox;
       MyHintergrund         : TImage;
       TMyVordergrund         : TImage;
    public
       Constructor create(Besitzer :TForm);
       Destructor destroy;
       Procedure SetPos (PosX,PosY : Integer);
       Procedure SetSize (XHeight,YWidth : Integer);
       Procedure HintergrundLaden(Filename : String);
       Procedure Zeigen;
  end;
 
implementation
 
{ TSpielfeld }
 
constructor TSpielfeld.create(Besitzer: TForm);
begin
  //Scrollbox erzeugen
  inherited Create;
  MyScrollbox := TScrollbox.Create(Besitzer);
  MyHintergrund :=TImage.Create(MyScrollbox);
end;
 
destructor TSpielfeld.destroy;
begin
   MyScrollbox.Free;
end;
 
procedure TSpielfeld.SetPos(PosX, PosY: Integer);
begin
  MyScrollbox.Top:=PosX;
  MyScrollbox.Left:=PosY;
end;
 
procedure TSpielfeld.SetSize(XHeight, YWidth: Integer);
begin
  MyScrollBox.Width:=YWidth;
  MyScrollBox.Height:=XHeight;
end;
 
procedure TSpielfeld.HintergrundLaden(Filename: String);
begin
  MyHintergrund.Picture.LoadFromFile(Filename);
end;
 
procedure TSpielfeld.Zeigen;
begin
  MyHintergrund.Top:=MyScrollbox.Top;
  MyHintergrund.Left:=MyScrollbox.Left;
  MyHintergrund.AutoSize:=True;
  MyScrollbox.Visible:=True;
  MyScrollbox.Enabled:=True;
  Myscrollbox.Show;           //klappt net
end;
 
end.  


und hier, wie ich es sehen will

Code: Alles auswählen

 
procedure TForm4.Button1Click(Sender: TObject);
Var
  Filename : String;
begin
  if OpenPictureDialog1.Execute then Filename := OpenPictureDialog1.FileName;
  Testfeld := TSpielfeld.create(Form4);
  Testfeld.SetPos(20,20);
  Testfeld.SetSize(300,300);
  Testfeld.HintergrundLaden(Filename);
  Testfeld.Zeigen;
end;


Ihr könnt mich ruhig steinigen!!

Benutzeravatar
theo
Beiträge: 10873
Registriert: Mo 11. Sep 2006, 19:01

Re: Klasse soll VCL Kompenten erzeugen Man sieht nichts

Beitrag von theo »

Parent Eigenschaft setzen. irgendwo muss es ja drauf sein.

MAC
Beiträge: 770
Registriert: Sa 21. Feb 2009, 13:46
OS, Lazarus, FPC: Windows 7 (L 1.3 Built 43666 FPC 2.6.2)
CPU-Target: 32Bit

Re: Klasse soll VCL Kompenten erzeugen Man sieht nichts

Beitrag von MAC »

Richtig, das hier:

Code: Alles auswählen

MyScrollbox := TScrollbox.Create(Besitzer);
bedeutet nicht das sich die Scrollbox in der Form Besitzer befindet, sondern soweit ich weis nur, das beim löschen der Form auch automatisch die Scrollbox mitgelöscht wird...
Also

Code: Alles auswählen

MyScrollbox := TScrollbox.Create(Besitzer);
MyScrollbox.parent := Besitzer;
und dementsprechend auch für den MyHintergrund...
Und beim Buttonklick für das Testfeld...

Code: Alles auswählen

Signatur := nil;

klausi1305
Beiträge: 35
Registriert: Mo 1. Jul 2013, 21:30
OS, Lazarus, FPC: Win 7 Laz 1.0.10
CPU-Target: 32 Bit
Wohnort: Leipzig

Re: Klasse soll VCL Kompenten erzeugen Man sieht nichts

Beitrag von klausi1305 »

Danke für die Hilfe...

jedoch hänge ich daran, wenn ich 2 Images übereinander in die Scrollbox packen will, der Hintergrund wird brav angezeigt, jedoch der Vordergrund auf dem was gezeichnet wird nicht. Schalte ich per Checkbox den Hintergrund Visible:= FALSE sehe ich nur den grauen Hintergrund?

Wo ist der Vordergrund?
btw. das ganze funktioniert ja, wenn ich die Scrollbox und die 2 Images per Objektinspektor erstelle. Ich versuche durch das erstellen meiner Klasse TSpielfeld mir ne Menge Arbeit für später abzunehmen...

Code: Alles auswählen

 
{ TSpielfeld }
 
constructor TSpielfeld.create(Besitzer: TForm);
begin
  //Scrollbox erzeugen
  inherited Create;
  MyScrollbox := TScrollbox.Create(Besitzer);  //Scrollbox erzeugen
  MyScrollbox.Parent :=Besitzer;
  //Hintergrund erzeugen
  MyHintergrund :=TImage.Create(MyHintergrund);  //Hintergrund Imgage erzugen
  MyHintergrund.Parent:= MyScrollbox;
  MyHintergrund.Top:=0;
  MyHintergrund.Left:=0;
  MyHintergrund.AutoSize:=True;                //  Autosize setzen
  //Vordergrund erzeugen
  MyVordergrund :=TImage.Create(MyVordergrund);//Vordergrund Image erzeugen
  MyVordergrund.Parent:= MyScrollbox;
  MyVordergrund.Top:=0;
  MyVordergrund.Left:=0;
  //Größe Vordergrund an Hintergrund anpassen
  MyVordergrund.Width:=MyHintergrund.Picture.Width;                          //Vordergrund an Hintergrund anpassen
  MyVordergrund.Height:=MyHintergrund.Picture.Height;                        //Vordergrund an Hintergrund anpassen
  MyVordergrund.AutoSize:=true;                                              //  Autosize setzen
  //Transparenz setzen
  MyVordergrund.Canvas.Brush.Color:=$FF0000;                       //Hintergrundfarbe, die Transparent erscheinen soll
  MyVordergrund.Canvas.FillRect(0,0,MyVordergrund.Width,MyVordergrund.Height);   //mit transparenter Farbe Hintergrund füllen
  MyVordergrund.Picture.Bitmap.TransparentColor:=$FF0000;          //setzen der transparenten Farbe
  MyVordergrund.Picture.Bitmap.TransparentMode:=tmFixed;           //Modus
end;                                                       


und hier wird gezeichnet auf dem Vordergrund

Code: Alles auswählen

procedure TSpielfeld.GitternetzZeigen(Kantenlaenge,AnzfelderBreite,AnzFelderHoehe : Integer);
Var
  Zaehler1, Zaehler2 : Integer;
 
begin
  {-------------Gitter 37x37 auf Vordergrund zeichnen-------------------------}
 
             MyVordergrund.Transparent:=not MyVordergrund.Transparent;      // Transparenz an
             MyVordergrund.Picture.Bitmap.Canvas.Pen.Color:=CLred;        // Linienfarbe des Gitters
 
             //Zeichnen der Gitterlinien von Links nach Rechts
             Zaehler1:=-1;
             Zaehler2:=-37;
             Repeat
               inc(Zaehler1);
               inc(Zaehler2,37);
               MyVordergrund.Picture.Bitmap.Canvas.MoveTo(Zaehler2,0);
               MyVordergrund.Picture.Bitmap.Canvas.lineTo(Zaehler2,MyVordergrund.Height);
             until Zaehler1 = AnzfelderBreite;
 
             //Zeichnen der Gitterlinien von Oben nach Unten
             Zaehler1:=-1;
             Zaehler2:=-37;
             Repeat
               inc(Zaehler1);
               inc(Zaehler2,37);
               MyVordergrund.Picture.Bitmap.Canvas.MoveTo(0,Zaehler2);
               MyVordergrund.Picture.Bitmap.Canvas.lineTo(MyVordergrund.Width,Zaehler2);
             until Zaehler1 = AnzFelderHoehe;
end;

Michl
Beiträge: 2511
Registriert: Di 19. Jun 2012, 12:54

Re: Klasse soll VCL Kompenten erzeugen Man sieht nichts

Beitrag von Michl »

Ich weiss nicht, ob das ein Bug ist?!

Die Canvas wird afaik von Windows zur Verfügung gestellt, Transparenzen funktionieren da glaube ich nicht. Bin nicht Fachmann genug, um das Verhalten zu deuten, ob Bug oder Feature (denke aber Feature)?!

Einen Workaround hatte ich dir im Post http://www.lazarusforum.de/viewtopic.php?f=55&t=7058 gezeigt:

Code: Alles auswählen

  Image2.Picture.SaveToFile('Image2.bmp','bmp');            
  Image2.Picture.LoadFromFile('Image2.bmp');
so wird das Canvas auf ein Bitmap vereint. Bitmaps werden ordentlich mit Transparenz gezeigt. Evtl. kann man ohne Speichern mit SaveToStream und LoadFromStream den selben Effekt haben?! Evtl. gibt es noch eine andere Möglichkeit Canvas auf Bitmap zu bringen?! Evtl. weiss jemand einen besseren Weg?!

Code: Alles auswählen

type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection;  

klausi1305
Beiträge: 35
Registriert: Mo 1. Jul 2013, 21:30
OS, Lazarus, FPC: Win 7 Laz 1.0.10
CPU-Target: 32 Bit
Wohnort: Leipzig

Re: Klasse soll VCL Kompenten erzeugen Man sieht nichts

Beitrag von klausi1305 »

Wenn ich das Hintergrund Picture in das Vordergrund Image lade, gehts ja...das wundert mich...es ist ja da...

Deinen Workaround habe ich beachtet, jedoch als ich feststellte, dass es auch ohne geht, habe ich es erstmal weggelassen..

Michl
Beiträge: 2511
Registriert: Di 19. Jun 2012, 12:54

Re: Klasse soll VCL Kompenten erzeugen Man sieht nichts

Beitrag von Michl »

Folgenden Fehler habe ich noch entdeckt, bei

Code: Alles auswählen

constructor TSpielfeld.create(Besitzer: TForm);
...
  MyVordergrund.Width:=MyHintergrund.Picture.Width;                          //Vordergrund an Hintergrund anpassen
  MyVordergrund.Height:=MyHintergrund.Picture.Height;                        //Vordergrund an Hintergrund anpassen
 
da MyHintergrund.Picture noch gar keinen Inhalt hat, ist die Größe jeweils undefiniert bzw. 0. Damit kann nachfolgende Zeilen

Code: Alles auswählen

  MyVordergrund.Canvas.FillRect(0,0,MyVordergrund.Width,MyVordergrund.Height);   //mit transparenter Farbe Hintergrund füllen 
nur einen Bereich von 0 x 0 Pixeln füllen. Müsstest daher eine andere Größe definieren.

Code: Alles auswählen

type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection;  

klausi1305
Beiträge: 35
Registriert: Mo 1. Jul 2013, 21:30
OS, Lazarus, FPC: Win 7 Laz 1.0.10
CPU-Target: 32 Bit
Wohnort: Leipzig

Re: Klasse soll VCL Kompenten erzeugen Man sieht nichts

Beitrag von klausi1305 »

mmhh..bin ich doof!!!! :shock:

Klar, wenn kein Picture geladen wird, woher soll ich da ne Größe haben....
Ich habe das Hintergrundbild erst geladen, als ich das Create schon erledigt hatte...
Wieder was gelernt...wirklich jede Variable die benutzt wird mit dem "Überwachte Ausdrücke" Dialog durchforsten!!

Vielen Dank für die Lehrstunde!

Antworten