24. december 2008 - 14:52Der er
16 kommentarer og 1 løsning
Ændre caption på form
Jeg sidder med en form i Delphi 2009 hvor jeg gerne vil ændre Caption i fobindelse med nogle valg der foretages. Men af en eller anden grund vil den bare ikke ændre sig. Jeg skriver frmRemoteControl.Caption := 'Remotecontrol : ' + strCommand_String;
Er der nogle properties jeg kan have sat der forhindrer dette?
I dette særtema om aspekter af AI ser vi på skiftet fra sprogmodeller til AI-agenter, og hvordan virksomheder kan navigere i spændet mellem teknologisk hastighed og behovet for menneskelig kontrol.
Nu har jeg ikke D2009 men det burde vel virke ligesom i D7. Er du sikker på at koden bliver kaldt, prøv at indsætte et breakpoint og check værdien af strCommand_String ved break.
normalt skulle delphi være ligeglad med om man refere til caption endten via Form1.Caption eller Caption. men jeg skal ikke kunne sige om de har ændret en del på delphi's core i den retning. jeg holder mig stadig til Delphi 7 og Lazarus
nu tror jeg der er en klokke der ringer.... prøver du at skrive til formens caption property før du har created den? i så fald så kan delphi godt drille hvad det angår.
Lazarus er et Open Source udviklingsmiljø der liger meget delphi men benytter Free Pascal Compileren som er en åben object pascal compiler. fordelen ved lazarus er at du kan lave et program som du kan kompliere til mange forskellige platforme fx Linux, Windows, Mac OS X, windows Mobile og forskellige processore 32 og 64 bit intel, 32 og 64 bit PowerPC eller ARM bare for at nævne et par stykker. den klart store fordel ved lazarus er at du kun behøves at skrive koden een gang og der efter vælge hvilke platforme dit program skal køre under og kompliere det. det giver langt større flexibillitet :)
Hvis du (i D7) creater Form1 flere gange, har du kun adgang til den sidst oprettede gennem objektangivelsen 'form1.xxx'. Hvis du istedet anvender 'self.xxx', kan du have flere instanser af den samme form.
Det er også derfor din ændrede kode virker. Her er 'self' uderforstået foran Caption.
Du kan også prøve fra 'hovedprogrammet' - Der hvor du creater 'Form1' at udføre
Form1.visible := true; eller Form1.show;
Du kan gennemgå alle dine "Forms" med kode som
i := 0 to screen.formCount-1; screen.Forms[i].Caption
Du skal aldrig bruge den globale instansvariabel (her frmRemoteControl) inde i formen. Det er en kilde til meget ondt. Inde i klassen (TfrmRemoteContro) refererer man til instansen vha. self.
I dette tilfælde er den ikke initialiseret og så prøver du at finde caption i en form-instans der ikke er oprettet (og så derfor sikkert er nil, hvorved den fejler.
Det første man egentlig bør gøre når man opretter en ny form er, at slette ovennævnte globale variabel. Det hører ind under ordentlige programmeringsrutiner.
Din variabelinstans skal eksistere inden du creater:
var frmRemoteControl = TfrmRemoteControl;
begin frmRemoteControl := TfrmRemoteControl.create(application); frmRemotecontrol.show; frmRemotecontrol.caption := 'Create1';
frmRemoteControl := TfrmRemoteControl.create(application); // du taber her adgangen det første objekt gennem instansvariablen frmRemoteControl // men du kan stadig gå til det via 'screen'.... som eksemplificeret ovenfor. frmRemotecontrol.caption := 'Create2'; // vil ikke blive vist da den nye form stadig ikke er vist (show ikke udført) end;
hugo: det er ret forstået. Den globale variabel er en plage, især fordi mange gør som du, bruger den inde i klassen da de ikke kender eksistensen af "self" (a.k.a. "this" for C++ et al). Jeg gør meget ud af at undgå variablen. Hvis jeg f.eks. har en dialog hvor parametre til en QuickReport sættes, så lader jeg ikke QReport-formen snage i formen, men sender en (hjemmelavet) TParamData - klasse over. Den indeholder alle parametre som rapporten skal bruge. På den måde opnår jeg, at begge de to forme behøver kende hinanden. Parameterformen kender rapporten, men rapporten kender ikke formen der kalder den.
Endelig benytter jeg meget at modificere constructoren (her, i quickreport formen):
Laver en parameterunit som begge forme linker til (parameterformen linker i implementation-delen, mens rapportformen gør det under interface)
unit UParamData;
type TParamData = class private fFraDato: TDateTime; fTilDato: TDateTime; procedure SetDateTime(const Index: integer; const aValue: TDateTime); public constructor Create; // Initialisér attributter property FraDato: TDateTime index 0 read fFraDato write SetDateTime; property TilDato: TDateTime index 1 read fTilDato write SetDateTime; function IsValid: boolean; end;
// Demonstrerer brugen af Index'et i property-listen. Det smarteste er at bruge // konstanter til indekserne procedure TParamData.SetDateTime(const Index: integer; const aValue: TDateTime); begin case Index of 0: fFraDato := DateOf(aValue); 1: fTilDato := DateOf(aValue); end; end;
function TParamdata.IsValid: boolean; begin result := (fFraDato <> 0) and (fTilDato <> 0) and (fFraDato <= fTilDato); end;
// Lidt af parameterformen har vi her
implementation
uses UParamData;
procedure TfrmRapportParams.DoReport(Sender: TObject); var ParamData: TParamData; frmQRapportForm: TfrmQRapportForm; // Kun lokale variable!! begin ParamData := TParamData.Create; ParamData.FraDato := dtpFraDato.Date; ParamData.TilDato := dtpTilDato.Date;
// .. osv
frmQRapportForm := TfrmQRapportForm.Create(self,ParamData); try if Sender = btnPrint then frmQRapportForm.QuickRep.Print else frmQRapportForm.QuickRep.Prewiev; finally frmQRapportForm.Release; // eller free. Er i tvivl når det gælder QReport ParamData.Free; end; end;
// I Rapport-formen har jeg modificeret constructoren (lad være med at bruge OnCreate // sammen med sådan en konstruktion, for det virker ikke):
interface
uses SysUtils, Classes, UParamData ...;
type TQuickreportForm = class(TForm) private fParamData: TParamData; public constructor Create(aOwner: TComponent; aParamData: TParamData); reintroduce; end;
implementation
procedure TQuickRepForm.Create(aOwner: TComponent; aParamData: TParamData); begin inherited Create(aOwner); fParamData := aParamData; // Gem "pointeren" til parameterklassen end;
---------- EOE (End of Example) ----------
Det ser måske lidt omstændigt ud, men koden er sikker og stringent. Jeg har ikke fundet pænere løsning og bruger den på rygradden. Det er meget let at tilføje nye parametre. Desuden kan man validere og smukkesere data (her laver jeg f.eks. en TDateTime om til en TDate).
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.