![]() |
Laufzeitfehler mit eigenem Typ
Hallo DP,
ich möchte gerne zur Laufzeit meines Programmes eine eigene Klasse erstellen. Diese Klasse soll einen Computer repräsentieren und zwei Label für den Namen und die IP-Adresse besitzen.
Delphi-Quellcode:
So habe ich den Typ definiert und nun möchte ich gerne eine Instanz davon erzeugen, sodass die Labels auch sichtbar werden.
type
TLCComputer = class public Name, IP: TLabel; Column, Row: integer; end; Mit Computers vom Typ "array of TLCComputers" versuche ich per
Delphi-Quellcode:
zur Laufzeit die Label zu erstellen und auf dem Formular "FrmLC" zu erschaffen.
SetLength(Computers, Length(Computers) + 1);
Computers[Length(Computers)-1].Name := TLabel.Create(self); Computers[Length(Computers)-1].Name.Parent := FrmLC; Computers[Length(Computers)-1].Name.Left := Column * (cComputerWidth + cComputerSpaceV); Computers[Length(Computers)-1].Name.Top := Row * (cComputerHeight + cComputerSpaceH); Computers[Length(Computers)-1].IP := TLabel.Create(self); Computers[Length(Computers)-1].IP.Parent := FrmLC; Computers[Length(Computers)-1].IP.Left := Column * (cComputerWidth + cComputerSpaceV); Computers[Length(Computers)-1].IP.Top := Row * (cComputerHeight + cComputerSpaceH) + 10; Jedoch erhalte ich beim Start stets nur Zugriffsverletzungen... Was mache ich falsch? Schonmal danke für eure Hilfe! greetZ 64Jabor |
Re: Laufzeitfehler mit eigenem Typ
Und wo erstellst du die Klasse? ;-)
// EDIT: Nebenbei: Wie wäre es mit einer Integervariablen, in der du den Index speicherst? ;-) |
Re: Laufzeitfehler mit eigenem Typ
In einer eingebunden Unit
//ja das macht Sinn :D Aber erstmal hat mir das STR+C drücken Spaß gemacht xD |
Re: Laufzeitfehler mit eigenem Typ
Zitat:
Ok, wenn die Klasse erstellt ist, dann sollte das soweit korrekt sein. |
Re: Laufzeitfehler mit eigenem Typ
Meinst du das
Delphi-Quellcode:
oder die gesamte Unit?
uses MyUnits;
Die Unit wäre:
Delphi-Quellcode:
Habe zur Sicherheit mal alles eingebunden xD
unit uLC_Computer;
interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ComCtrls, ExtCtrls, StdCtrls; type TLCComputer = class public Name, IP: TLabel; Column, Row: integer; end; implementation end. |
Re: Laufzeitfehler mit eigenem Typ
Ja, aber irgendwo musst du doch die Klasse TLCComputer in deinem Array erstellen. Den entsprechenden Teil des Quelltextes hast du nicht gepostet oder du machst das gar nicht...
Delphi-Quellcode:
Freigeben darfst du am Ende natürlich nicht vergessen, wenn das Programm beendet wird.
SetLength(Computers, Length(Computers) + 1);
Computers[High(Computers)] := TLCComputer.Create; Warum nimmst du eigentlich nicht einfach eine TObjectList statt des Arrays? OwnsObjects auf True und du musst dich um die Freigabe nicht mehr kümmern. |
Re: Laufzeitfehler mit eigenem Typ
Die Klasse sollte die Labels selbst erstellen und nicht public zugänglich machen ;)
Also einen Konstruktor rein und am besten gleich von T(Win)Control ableiten, dann kann die Klasse die Labels auch direkt beinhalten. So könnte man auch direkte 2 Arrays für die Labels nehmen. Das eigene Control hat noch den Vorteil, dass die Labels zueinander leichter ausgerichtet werden können ;) |
Re: Laufzeitfehler mit eigenem Typ
er meint wo erstellst du diese Klasseninstanz?
> TLCComputer.Create
Delphi-Quellcode:
und vergiß nicht deine Klasse auch wieder mit .Free freizugeben, wenn du sie löschts :!:
SetLength(Computers, Length(Computers) + 1);
Computers[High(Computers)] := TLCComputer.Create; Computers[High(Computers)].Name := TLabel.Create(self); ... PS: warum eine Klasse? so wie es jetzt ist, reicht ein Record auch aus und der muß nicht erst erstellt werden. :angel2: |
Re: Laufzeitfehler mit eigenem Typ
Uhm also ich gebe die "Computers" wieder frei in der OnClose.
Ich definiere das Array aus meiner Klasse in dem private-Teil des Formulares:
Delphi-Quellcode:
Eine TObjectList? Das werde ich mir mal näher ansehen!
private
{ Private-Deklarationen } Computers: Array of TLCComputer; Oh man, ja ich hatte ja gar keine Instanz der Klasse erstellt -.- Vielen Dank! Nun ich möchte es recht einfach halten, wäre das dann mit record oder eher mit der ObjectList einfacher? Ich kenne mich damit noch nicht so aus, ich hab vorher noch nie eine Klasse erstellt :coder: //edit Wenn ich eine Instaz der Klasse vorher erstelle bleibt der Zugriffsfehler aus, super! |
Re: Laufzeitfehler mit eigenem Typ
Also ich habe die Klasse jetzt folgendermaßen abgeändert:
Delphi-Quellcode:
Ich erstelle nun einen neuen Computer per
unit uLC_Computer;
interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ComCtrls, ExtCtrls, StdCtrls; const cComputerWidth = 100; cComputerHeight = 100; cComputerSpaceV = 10; cComputerSpaceH = 10; type TLCComputer = class(TWinControl) private Name, IP: TLabel; Column, Row: integer; public constructor Create(NName, NIP: string; Column, Row: integer); end; implementation constructor TLCComputer.Create(NName, NIP: string; Column, Row: integer); begin Name := TLabel.Create(self); Name.Parent := self; Name.Caption := NName; Name.Left := Column * (cComputerWidth + cComputerSpaceV); Name.Top := Row * (cComputerHeight + cComputerSpaceH); IP := TLabel.Create(self); IP.Parent := self; IP.Caption := NIP; IP.Left := Column * (cComputerWidth + cComputerSpaceV); IP.Top := Row * (cComputerHeight + cComputerSpaceH) + 10; end; end.
Delphi-Quellcode:
Dabei kommen zwar keine Fehler mehr auf, aber die Labels werden nicht sichtbar...
procedure TFrmLC.BtnAddComputerClick(Sender: TObject);
var Name, IP: string; Column, Row: integer; begin Name := InputBox('Computername', 'Bitte geben Sie einen Computernamen an:', ''); IP := InputBox('IP-Adresse', 'Bitte geben Sie die IP-Adresse des Computers an:', ''); SetLength(Computers, Length(Computers) + 1); Computers[Length(Computers)-1] := TLCComputer.Create(Name, IP, Column, Row); end; Muss ich die Parent-Eigenschaft der Labels etwa zwingend auf mein Formular setzen? //edit: Sorry fürs Doppelpost :roll: |
Re: Laufzeitfehler mit eigenem Typ
Du könntest einen Owner als Parameter im Konstruktor angeben lassen. Dann könntest Du in demselben auch
Delphi-Quellcode:
aufrufen.
inherited Create(Owner);
[edit] Einen Parent könntest Du dann natürlich auch gleich mit angeben. [/edit] |
Re: Laufzeitfehler mit eigenem Typ
Zitat:
Es wurde ja bereits gesagt, dass es vielleicht sinnvoller wäre z.B. von TWinControl abzuleiten und eine richtige Komponente daraus zu machen. Dann könntest du dir die Label auch gleich sparen und könntest den Text selbst ausgeben... |
Re: Laufzeitfehler mit eigenem Typ
Ja ich habe meine Klasse ja von TWinControl abgeleitet!
Dann übergeben ich also nun den Owner und den Parent dem Konstruktor, mal sehen was draus wird :D |
Re: Laufzeitfehler mit eigenem Typ
Zitat:
Kann es sein, dass du die Größe des WinControls oder dessen Parent nirgends setzt? |
Re: Laufzeitfehler mit eigenem Typ
Also ich setze die Größe, also Width und Height, meiner Klasse im Konstruktor, das habe ich erst nach meinem Post eingefügt, vorher vergessen!
Die der Label setze ich nicht, in der Hoffnung auf AutoSize :D Der Owner der Label, also meine Klasse, übergebe ich deren Konstruktoren. Der Owner meiner Klasse ist das Formular. Dennoch ist kein Label sichtbar =/ |
Re: Laufzeitfehler mit eigenem Typ
Und du setzt Parent deines WinControls auf das Formular und das der Labels auf dein WinControl?
|
Re: Laufzeitfehler mit eigenem Typ
Ja das tue ich, wobei ja Owner und Parent in meinem Fall immer dasselbe Objekt sind, oder nicht?
|
Re: Laufzeitfehler mit eigenem Typ
Owner und Parent wovon? Der Komponente oder der Labels?
|
Re: Laufzeitfehler mit eigenem Typ
Naja in beiden Fällen.
Den Owner der Label (meine Klasseninstanz) habe ich ja auch dem Konstruktor der Label übergeben und setze danach deren parent wiederum auf meine Klasseninstanz. Bei der Klasseninstanz selber verwende ich erst das
Delphi-Quellcode:
und setze dann auch wieder den parent auf das Formular...
inherited Create(Owner);
|
Re: Laufzeitfehler mit eigenem Typ
Das klingt zumindest richtig.
|
Re: Laufzeitfehler mit eigenem Typ
:D
Hmm also ich denke ich poste den "gesamten" Code nochmal, eventuell ist im Zusammenhang alles etwas klarer...
Delphi-Quellcode:
Und die Erstellung der Klasseninstanz:
constructor TLCComputer.Create(NName, NIP: string; Column, Row: integer; NOwner: TWinControl);
begin inherited Create(NOwner); Parent := NOwner; Width := cComputerWidth; Height := cComputerHeight; Name := TLabel.Create(self); Name.Parent := self; Name.Caption := NName; Name.Left := Column * (cComputerWidth + cComputerSpaceV); Name.Top := Row * (cComputerHeight + cComputerSpaceH); IP := TLabel.Create(self); IP.Parent := self; IP.Caption := NIP; IP.Left := Column * (cComputerWidth + cComputerSpaceV); IP.Top := Row * (cComputerHeight + cComputerSpaceH) + 10; end;
Delphi-Quellcode:
Keine Laufzeitfehler, keine Compilerfehler, läuft einwandfrei nur passieren tut nix ^^
procedure TFrmLC.BtnAddComputerClick(Sender: TObject);
var Name, IP: string; Column, Row: integer; begin Name := InputBox('Computername', 'Bitte geben Sie einen Computernamen an:', ''); IP := InputBox('IP-Adresse', 'Bitte geben Sie die IP-Adresse des Computers an:', ''); SetLength(Computers, Length(Computers) + 1); Computers[Length(Computers)-1] := TLCComputer.Create(Name, IP, Column, Row, self); end; //edit: mir ist bewusst dass durch fehlende Angabe von Column und Row die Left und Top-Werte der label 0 werden, aber das ist ja nicht schlimm |
Re: Laufzeitfehler mit eigenem Typ
Und beim Durchsteppen wird auch alles durchlaufen? Hast Du den Konstruktor auch überschrieben?
|
Re: Laufzeitfehler mit eigenem Typ
Ich vermute einfach mal, die Labels sind unsichtbar, weil sie nicht mehr im Ciontrol sind ;)
Du erstellst du Labels und setzt das Parent auf "Self" - das sit gut so, aber die Left und die Top-Eigenschaft des Labels sind nun relativ zur oberen linken Ecke des Parents (= Des neuen Controls) Proibier mal das so:
Delphi-Quellcode:
;)
constructor TLCComputer.Create(NName, NIP: string; NOwner: TWinControl);
// Column und Row sollten nur in dem Formular eine Rolle spielen begin inherited Create(NOwner); Parent := NOwner; Width := cComputerWidth; // Sind das globale Variablen? Height := cComputerHeight; Name := TLabel.Create(self); Name.Parent := self; Name.Caption := NName; Name.Left := 5; Name.Top := 5; IP := TLabel.Create(self); IP.Parent := self; IP.Caption := NIP; IP.Left := 5; IP.Top := 20; end; |
Re: Laufzeitfehler mit eigenem Typ
Ja auch in Einzelschritten wird alles brav durchlaufen.
Den Konstructor überschrieben?
Delphi-Quellcode:
Den Rest kennst du ja...
type
TLCComputer = class(TWinControl) private Name, IP: TLabel; Column, Row: integer; public constructor Create(NName, NIP: string; Column, Row: integer; NOwner: TWinControl); end; //edit: Wenn ich Left und Top explizit angebe, erscheinen die Labels! Mit Colum und Row wollte ich die Klasseninstanzen später ansprechen, aber das kann ich ja jetzt auch per OnClick auf das TWinControl, nicht? |
Re: Laufzeitfehler mit eigenem Typ
Also liegt es an den Koordinaten. Und mit Überschreiben meinte ich das Wörtchen override.
|
Re: Laufzeitfehler mit eigenem Typ
Nunja es klappt auch ohne...Soll ich trotzdem verwenden?
|
Re: Laufzeitfehler mit eigenem Typ
Ich würde es tun.
|
Re: Laufzeitfehler mit eigenem Typ
Okay, aber es funktioniert jetzt alles wunderbar, ich übergebe die Left und Top-Werte der Computerinstanz und positioniere relativ dazu die beiden Labels, und sie werden angezeigt!
Vielen Dank euch allen! :dp: |
Alle Zeitangaben in WEZ +1. Es ist jetzt 18:06 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