| Autor |
Beitrag |
faB
Hält's aus hier
Beiträge: 6
Delphi 6
|
Verfasst: Do 27.10.05 17:47
Hi ich bin relativ unerfahren mit delphi 6 und hab nen problem mit meinem programm.
Das programm soll button in nem timer erstellen und diese sollen auf anklicken gelöscht werden.
nun erhalte ich aber wenn ich einen der neu durch den timer erstellten button anklicke einen abstackten fehler und dies überfordert mich deutlich.
der programm text:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97:
| unit aiming;
interface
uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls;
type TForm1 = class(TForm) Timer1: TTimer; btstart: TButton; btnoch: TButton; btende: TButton; procedure Timer1Timer(Sender: TObject); procedure btstartClick(Sender: TObject); procedure klicken(Sender: TObject); procedure btendeClick(Sender: TObject); private public end;
var Form1: TForm1; neubutton, welcher : tbutton; y, F, z , n ,c: integer ; i: integer; r: integer;
implementation
{$R *.dfm}
procedure TForm1.Timer1Timer(Sender: TObject); begin
n:=1; while i >=1 do begin neubutton:=tbutton.create(form1); neubutton.setbounds(1+random(220),1+random(200),15,15); neubutton.caption:=inttostr(n); neubutton.name:= ('button'+inttostr(n)); n:= n+1; neubutton.parent:=form1; neubutton.OnClick:= klicken; i:= i-1 end; r:= r-1; end;
procedure TForm1.btstartClick(Sender: TObject); begin timer1.Enabled:=true; n:=1; i := 10; r:= 10; end;
procedure tform1.Klicken(Sender: TObject); begin F:=componentcount -1 ; c:=componentcount -1 ;
while F >= 0 DO BEGIN if (sender = components[F]) then begin WHILE c >= 0 DO BEGIN if (tbutton(components[F]).name= ('button'+inttostr(c))) then begin welcher:= tbutton(components[F]); welcher.visible:=false; welcher.destroy;
end; c:=c-1; end;
end; F:=F-1; end;
end;
procedure TForm1.btendeClick(Sender: TObject); begin close; end;
end. |
ich hoffe mir kann jemand meinen fehler nenen !
danke schon mal
Moderiert von Christian S.: Delphi-Tags hinzugefügt.
|
|
Martin1966
      
Beiträge: 1068
Win 2000, Win XP
Delphi 7, Delphi 2005
|
Verfasst: Do 27.10.05 18:02
Hallo und willkommen in der Ecke!!
Das Problem ist wohl, dass Du die Buttons mit der Methode Destory freigeben willst. Das ist aber falsch. Verwende statt Destroy die Methode Free!
Außerdem verstehe ich nicht so ganz warum Du so umständlich die Buttons ermittelst. Über den Parameter Sender erhälst du doch schon eine Referenz auf den Button. Versuche mal folgende Procedure:
Delphi-Quelltext 1: 2: 3: 4: 5:
| procedure tform1.Klicken(Sender: TObject); begin If (Sender is TButton) Then Sender.Free; end; |
Außerdem solltest du mal die ganzen globalen Variablen entfernen und nur da definieren wo sie gebraucht werden.
Lg Martin
_________________ Ein Nutzer der Ecke
|
|
faB 
Hält's aus hier
Beiträge: 6
Delphi 6
|
Verfasst: Do 27.10.05 18:09
danke erst mal für die antwort
wenn ich deinen text übernehme erhalte ich auch einen abstrackten fehler.....
eben so wenn ich das destroy dur free ersetze..
ich ermittel den button so weil es noch andere button und components gibt ...
es würde jedenfalls zu komplikationen kommen .. meine ich glaube ich ..
zitat aus delphi hilfe zum thema procedure free
Warunung
Sie dürfen eine Komponente nie in einer ihrer eigenen Ereignisbehandlungsroutinen oder in einer Ereignisbehandlungsroutine eines untergeordneten Objekts freigeben. Geben Sie beispielsweise auf keinen Fall eine Schaltfläche oder ihr übergeordnetes Formular in der OnClick-Ereignisbehandlungsroutine der Schaltfläche frei.
|
|
GTA-Place
      

Beiträge: 5248
Erhaltene Danke: 2
WIN XP, IE 7, FF 2.0
Delphi 7, Lazarus
|
Verfasst: Do 27.10.05 18:17
Ja, da haben wir ja schon das Problem:
Du könntest mal versuchen in OnClick auf eine andere Procedure weiterzuleiten,
also noch eine Procedure mit dem Namen "DestBut" o.Ä. In dieser löscht du
dann erst den Button.
_________________ "Wer Ego-Shooter Killerspiele nennt, muss konsequenterweise jeden Horrorstreifen als Killerfilm bezeichnen." (Zeit.de)
|
|
BenBE
      
Beiträge: 8721
Erhaltene Danke: 191
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: Do 27.10.05 18:37
Die Lösung besteht darin, TComponent(Sender).Release aufzurufen ... Siehe DOH für Hintergrundinfos ...
_________________ Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
|
|
faB 
Hält's aus hier
Beiträge: 6
Delphi 6
|
Verfasst: Do 27.10.05 22:33
also TComponent(Sender).Release soll ich einbinden in meinen programmtext?
in der DOH find ich nur TComponent_Release kann das sein?
dessweiten weiß ich leider nicht so wirklich genau WO ich das einbinden soll an dieser stelle sei noch mal betohnt das ich ein anfänger mit delphi bin.
ich hoffe jemand macht sich die mühe es mir verständlich zu machen
danke
|
|
Tino
      

Beiträge: 9839
Erhaltene Danke: 45
Windows 8.1
Delphi XE4
|
Verfasst: Do 27.10.05 22:39
Delphi-Quelltext 1: 2: 3: 4: 5:
| procedure tform1.Klicken(Sender: TObject); begin If (Sender is TButton) Then TComponent(Sender).Release; end; |
|
|
faB 
Hält's aus hier
Beiträge: 6
Delphi 6
|
Verfasst: Do 27.10.05 22:55
wenn ich den von timo erwähnten quell text benutze bekomme ich die fehler meldung das release ein undifinierter bezeichener sei..?!
mit anderen worten ich raff es immer noch nicht
|
|
BattleFrog
      
Beiträge: 53
WIN 2000
Delphi 7 Ent.
|
Verfasst: Fr 28.10.05 07:22
Release gilt nur für Formulare.
Komponenten und alles was mit .create erschaffen wird, werden mit .free wieder freigegeben. Punkt.
(Das Problem in diesem Fall ist wohl eher der Programmieransatz den Button bei Klick direkt freizugeben.
Das klingt logisch so falsch, dass ich garnicht den Grund dafür wissen muss, um zu sagen, das es auf jedenfall für kein Problem die Lösung sein kann.)
|
|
Gausi
      
Beiträge: 8554
Erhaltene Danke: 481
Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
|
Verfasst: Fr 28.10.05 08:04
Da du sowieso schon einen Timer hast, würde ich es so machen:
Im OnClick des Buttons diesen nicht freigeben, sondern nur "unsichtbar" machen. d.h. entweder Visible auf False, oder irgendwo hinverschieben, wo es der Nutzer nicht merkt. Zusätzlich diesen Button in ein Array of TButton einfügen.
Die Timerprozedur muss dann so erweitert werden, dass alle Buttons in dem Array mit free gelöscht werden.
_________________ We are, we were and will not be.
|
|
faB 
Hält's aus hier
Beiträge: 6
Delphi 6
|
Verfasst: Fr 28.10.05 08:05
???
was willst du mir mit deiner anmerkung in den klammern sagen???
Wie würdest du denn dafür sorgen das der button onclick gelöscht wird?
|
|
Muetze1
      
Beiträge: 346
|
Verfasst: Fr 28.10.05 09:10
Ich sehe den abstrakten Fehler woanders:
Delphi-Quelltext 1: 2:
| if (tbutton(components[F]).name= ('button'+inttostr(c))) then |
Anstatt vorher abzutesten ob die Komponente überhaupt ein Button ist, wird hier ein harter Typecast durchgeführt und dann auf die Eigenschaft eines Buttons (Name) zugegriffen, ohne Sicherheit, das es ein Button ist.
Ausserdem ist der TButton() Typecast hier eh afaik hinfällig, da TComponent schon die Eigenschaft "Name" mitbringt.
_________________ 49 63 68 68 61 62 65 6B 65 69 6E 65 41 68 6E 75 6E 67 21
|
|
faB 
Hält's aus hier
Beiträge: 6
Delphi 6
|
Verfasst: Fr 28.10.05 18:04
zu muetze :
ich hab das mal folgender maßen verändert
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30:
| procedure tform1.Klicken(Sender: TObject); begin
F:=componentcount -1 ; c:=componentcount -1 ;
while F >= 0 DO BEGIN if (sender = components[F]) and ( components[F] is tbutton ) then begin
WHILE c >= 0 DO BEGIN if(tbutton(components[F]).name= ('button'+inttostr(c))) then begin welcher:= tbutton(components[F]); welcher.visible:=false; welcher.destroy;
end; c:=c-1; end;
end; F:=F-1; end;
end; |
es hat nichts geholfen ...
|
|
Muetze1
      
Beiträge: 346
|
Verfasst: Fr 28.10.05 23:26
faB hat folgendes geschrieben: | zu muetze :
ich hab das mal folgender maßen verändert
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30:
| procedure tform1.Klicken(Sender: TObject); begin
F:=componentcount -1 ; c:=componentcount -1 ;
while F >= 0 DO BEGIN if (sender = components[F]) and ( components[F] is tbutton ) then begin
WHILE c >= 0 DO BEGIN if(tbutton(components[F]).name= ('button'+inttostr(c))) then begin welcher:= tbutton(components[F]); welcher.visible:=false; welcher.destroy;
end; c:=c-1; end;
end; F:=F-1; end;
end; |
es hat nichts geholfen ... |
So, nochmal für alle: Du willst beim Click auf einen Button den selbigen freigeben. Nun frage ich mich doch folgendes zu deinem jetzigen Code:
1. Sender ist der Button der geclicked wurde, also hast du die richtige Instanz - wozu also noch die ganze Komponentenliste durchsuchen?
2. Nicht Destroy sondern Free aufrufen - wurde schon gesagt.
3. Wenn du den Button im Components[] gefunden hast, warum brichst du dann nicht die Suche ab mit Break oder Exit o.ä. sondern läufst statt dessen weiter?
Grundlegendes Problem ist halt, wie oben schon erwähnt, die Freigabe des Elementes, welches genau diese Procedure aufruft und somit kehrt er in ein nicht mehr existierendes Objekt zurück. Daher empfehle ich dir entweder ein PostMessage mit CM_DESTROY oder WM_DESTROY an den Sender (TButton) zu senden.
Delphi-Quelltext 1: 2: 3: 4: 5:
| procedure tform1.Klicken(Sender: TObject); begin If ( Sender Is TButton ) Then PostMessage(TButton(Sender).Handle, WM_DESTROY, 0, 0); end; |
Das müsste doch so vollkommen reichen...
_________________ 49 63 68 68 61 62 65 6B 65 69 6E 65 41 68 6E 75 6E 67 21
|
|
AndyB
      
Beiträge: 1173
Erhaltene Danke: 14
RAD Studio XE2
|
Verfasst: Sa 29.10.05 01:31
_________________ Ist Zeit wirklich Geld?
|
|