Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi Änderung einer Deklarartion integer <-> double möglich? (https://www.delphipraxis.net/135636-aenderung-einer-deklarartion-integer-double-moeglich.html)

BAMatze 15. Jun 2009 07:52


Änderung einer Deklarartion integer <-> double möglich
 
Hallo und guten Morgen an alle DP´ler,

Hab mal eine allgemeine Frage. Kann ich in die Deklaration einer Property einer Komponente je nach Verwendung ändern?
Es geht um folgendes: Ich hab eine Komponente, in welche Ganzzahlen oder Gleitkommazahlen eingegeben werden können. Je nachdem welcher Typ durch den Benutzer eingestellt wird, soll die Property Value integer oder double sein. Gibt es eine Möglichkeit dies umzusetzen?
Leider hab ich zu dem Thema kein Threat gefunden, was sicherlich nicht daran liegt, dass es sie nicht gibt, sondern an den verwedeten Fachwörtern.

Vielen Dank
BAMatze

jfheins 15. Jun 2009 07:57

Re: Änderung einer Deklarartion integer <-> double mög
 
Eine Property mit veränderlichem Typ gibt es nicht. Mit fallen auf anhieb 2 Lösungen ein: 1. Variant benutzen - da kann man sowohl nen Integer als auch einen Double reinstecken. 2. Zwei Properties benutzen, eine für Integer und eine für Double ;)

jaenicke 15. Jun 2009 08:07

Re: Änderung einer Deklarartion integer <-> double mög
 
Eine Klasse zur Kapselung ginge auch. Und rein theoretisch wären auch noch ein variabler Record oder Pointer denkbar, aber beim Auslesen musst du doch sowieso mit dem richtigen Typ arbeiten (außer bei Variants). Deshalb verstehe ich nicht so ganz wie du dir das vorstellst. :gruebel:

BAMatze 15. Jun 2009 08:24

Re: Änderung einer Deklarartion integer <-> double mög
 
Naja Vorstellungen hatte ich bisher noch nicht so wirklich, deswegen hatte ich euch ja mal gefragt, was es dort gibt. Ich versuche es jetzt mal mit den Variants, so wie sich das anhört, scheinen die ja ausreichend variabel für mich zu sein, dass ich je nach den beiden Typen (double oder integer) meine Variable drauftun kann ohne Probleme dabei zu bekommen. Oder gibt es dort trotzdem etwas zu beachten, dass zu Problemen führen könnte?

jaenicke 15. Jun 2009 08:33

Re: Änderung einer Deklarartion integer <-> double mög
 
Zitat:

Zitat von BAMatze
Oder gibt es dort trotzdem etwas zu beachten, dass zu Problemen führen könnte?

Das wichtigste: Sie sind extrem langsam. Wenn du also viele Operationen durchführen willst, rate ich eher davon ab.

Ich glaube auch auf jeden Fall, dass es sicher eine bessere Lösung gibt.

BAMatze 15. Jun 2009 08:47

Re: Änderung einer Deklarartion integer <-> double mög
 
Zitat:

Zitat von jaenicke
Ich glaube auch auf jeden Fall, dass es sicher eine bessere Lösung gibt.

Also möchte eigentlich keine weiteren Operationen damit durchführen. Ich möchte eigentlich nur den Wert, der in meiner Komponente in einem TEdit steht variabel halten.
Im Programm soll dieser dann ganz normal auf den dementsprechend richtigen Typen draufgeschrieben werden ala:
Delphi-Quellcode:
  iWert := Komponente.Value
  // oder ebend
  dWert := Komponente.Value
Würde das gehen?

mkinzler 15. Jun 2009 08:53

Re: Änderung einer Deklarartion integer <-> double mög
 
Dann nimm einen Variant und entsprechende Methoden

himitsu 15. Jun 2009 09:15

Re: Änderung einer Deklarartion integer <-> double mög
 
Soll der Typ wärend der Laufzeit geändert werden könne,
oder reicht es, wenn man ihn zum Compilieungszeitpunkt festlegen kann?

siehe himXML ... die Klassen da lassen sich mit unterschiedliche Typendefinitionen kompilieren, aber diese sind dann zur Laufzeit unveränderbar.

Reinhard Kern 15. Jun 2009 11:57

Re: Änderung einer Deklarartion integer <-> double mög
 
Zitat:

Zitat von BAMatze
Also möchte eigentlich keine weiteren Operationen damit durchführen. Ich möchte eigentlich nur den Wert, der in meiner Komponente in einem TEdit steht variabel halten.
Würde das gehen?

Hallo,

grundsätzlich geht immer alles, ist bloss eine Frage des Aufwands. Ich benutze im Folgenden einen Record mit case of, keine Delphi Varianten. Wichtig: es gibt für jeden Typ einen Constructor, und der legt auch für den Rest des Lebens den Typ fest. Abgerufen werden die Werte mit Object.GetInteger, Object.GetString usw. dadurch ist Typprüfung gegeben - ich benutze absichtlich kein Overloading, ich will lieber einen Fehler sehen, wenn ich mich vertan habe. Das mit der Konstruktion auch dyn. Array und Strings möglich sind (Casting mit TRKiniSettingRecordS anstatt TRKiniSettingRecord), tut hier nichts zur Sache. Ist nur ein unvollständiges Schema, keine Copy&Paste-Vorlage!!

Gruss Reinhard

Delphi-Quellcode:
   TRKiniSettingVariant = (sv_Undef,sv_String,sv_Bool,sv_Integer,
                           sv_Real,sv_Color,sv_Pen,sv_WinPos,sv_Font,sv_Binary);
{...}
   PRKiniSettingRecord = ^TRKiniSettingRecord;
   TRKiniSettingRecord = packed record
     SetupControl : TControl;
     dirty : boolean;
     removed : boolean;
       case TRKiniSettingVariant of
         sv_Undef  : (vUndef : int64);     { 8 bytes }
         sv_Bool   : (vBool : boolean);    { svWinpos }
         sv_Integer : (vInteger : longint);
         sv_Real   : (vReal : double);
         sv_Color  : (vColor : TColor);
         sv_Pen    : (vPen : longint);
       { sv_WinPos : see above }
       { sv_Binary,sv_String,sv_Font : see below }
     end;
    { record size : 20 b }

   PRKiniSettingRecordB = ^TRKiniSettingRecordB;
   TRKiniSettingRecordB = packed record
     SetupControl : TControl;
     dirty : boolean;
     removed : boolean;
     vBinary : TRKIniBinaryArray;
     BDummy : DWord;
     end;

   PRKiniSettingRecordS = ^TRKiniSettingRecordS;
   TRKiniSettingRecordS = packed record
     SetupControl : TControl;
     dirty : boolean;
     removed : boolean;
     vString : TRKIniDynString;
     BDummy : DWord;
     end;
{...}
   TRKiniSettingValue = class
     sType : TRKiniSettingVariant;
     gType : TRKIniSettingsGrouping;
     digits : Smallint;
     Uplink : TRKIniSettingTable;
     ForwardLink : TRKiniSettingValue;
     pGroupItems : PRKiniSettingRecord; { 0 : Default. 1..n : Items }
     IniGroup,IniItem : TRKiniSettingName;
     FirstRecord,FieldLength,ExtraRecords : word;
     procedure SetupGrouping (imax : Smallint);
     procedure  Create_General (imax : Smallint; IG,II : TRKiniSettingName;
                const Def; pCC : PAoTC; maxCC : Smallint; OwnerTable : TRKIniSettingTable);
     constructor Create_String (imax : Smallint; IG,II : TRKiniSettingName;
             Def : ShortString; EC : array of TEdit; OwnerTable : TRKIniSettingTable);
     constructor Create_Bool  (imax : Smallint; IG,II : TRKiniSettingName;
                    Def : Boolean; BC : array of TButtonControl; OwnerTable : TRKIniSettingTable);
     constructor Create_Integer (imax : Smallint; IG,II : TRKiniSettingName;
                    Def : longint; EC : array of TEdit; OwnerTable : TRKIniSettingTable);
{...}
     function GetString (ix : Smallint) : ShortString;
     function GetBool (ix : Smallint) : boolean;
     function GetInteger (ix : Smallint) : longint;
     function GetReal (ix : Smallint) : Double;
     function GetColor (ix : Smallint) : TColor;
     function GetPenWidth (ix : Smallint) : Smallint;
{...}
{ speziell für ein Projekt: }
  TBPMLogSettings = class (TRKIniSettingTable)
    public
    Station_Node       : TRKiniSettingValue; { group }
    Station_Description : TRKiniSettingValue; { group }
{...}
constructor TBPMLogSettings.CreateTable (IC : TRKIniClass);
var CSection : ShortString;

begin
inherited Create (IC);

with BLMainForm do
  begin
  CSection := 'Station';
  Station_Node      := TRKiniSettingValue.Create_Integer (-maxStationNo,CSection,
        'Node',0, [] ,self);
  Station_Description := TRKiniSettingValue.Create_String (-maxStationNo,CSection,
        'Description','', [] ,self);
{...}

himitsu 15. Jun 2009 12:09

Re: Änderung einer Deklarartion integer <-> double mög
 
vergiß aber nicht, daß bei Reinhard Kerns Lösung der Record selber freigegeben werden muß, wenn da etwas größeres drin enthalten ist, welches via Pointer referenziert ist und auch bei Objekten.

Delphi-Quellcode:
TIndex = Record
  ValueType:  (vtIntValue, vtStringValue);
  IntValue:   Integer;
  StringValue: String;
  Class Operator Implicit(      Value: Integer): TIndex;
  Class Operator Implicit(Const Value: String): TIndex;
  Class Operator Implicit(Const Value: TIndex): Integer;
  Class Operator Implicit(Const Value: TIndex): String;
End;
dieser Record ist z.B. 12 Byte groß,
regelt die Speicherfreigabe selber und man braucht keine Zuweisungsfunktionen aufrufen

Delphi-Quellcode:
Var X: TIndex;
  i: Integer;
  S: String;

X := i;
X := S;
S := X;
i := X;
praktisch wie Variant, nur etwas Schlanker.

Reinhard Kern 15. Jun 2009 12:18

Re: Änderung einer Deklarartion integer <-> double mög
 
Zitat:

Zitat von himitsu
vergiß aber nicht, daß bei Reinhard Kerns Lösung der Record selber freigegeben werden muß, wenn da etwas größeres drin enthalten ist, welches via Pointer referenziert ist und auch bei Objekten.

...
dieser Record ist z.B. 12 Byte groß,
regelt die Speicherfreigabe selber und man braucht keine Zuweisungsfunktionen aufrufen

...

Das ist eben ein andrer Fall: ich verwalte Ini-Einträge, und die sollen zwar verschiedene Typen verwalten können, aber der Typ darf NIEMALS wechseln. Deswegen auch kein Overloading, als integer festlegen und als string abrufen ist eben falsch (bei dir übrigens auch, nicht formal aber logisch, oder wertest du beim Lesen den Typ aus?).

Gruss Reinhard

Popov 15. Jun 2009 12:21

Re: Änderung einer Deklarartion integer <-> double mög
 
Zitat:

Zitat von BAMatze
Hallo und guten Morgen an alle DP´ler,

Hab mal eine allgemeine Frage. Kann ich in die Deklaration einer Property einer Komponente je nach Verwendung ändern?
Es geht um folgendes: Ich hab eine Komponente, in welche Ganzzahlen oder Gleitkommazahlen eingegeben werden können. Je nachdem welcher Typ durch den Benutzer eingestellt wird, soll die Property Value integer oder double sein. Gibt es eine Möglichkeit dies umzusetzen?
Leider hab ich zu dem Thema kein Threat gefunden, was sicherlich nicht daran liegt, dass es sie nicht gibt, sondern an den verwedeten Fachwörtern.

Variant wäre möglich. Der Code wird dadurch langsamer, aber du kannst alles damit machen. Du kannst als Integer anfangen, Double draus machen und dann sogar noch ein String ;)

Delphi-Quellcode:
var
  a: Variant;
begin
  a := 5;
  ShowMessage(IntToStr(a * 5));
  a := a / 2;
  ShowMessage(FloatToStr(a));
  a := 'a ist = ' + FloatToStr(a);
  ShowMessage(a);
end;
Das ist schon beinahe Visual Basic :D

himitsu 15. Jun 2009 12:27

Re: Änderung einer Deklarartion integer <-> double mög
 
Man könnte den Typ auswerten und entsprechend versuchen umzuwandeln, aber in meinem aktuellen Fall ist dieses nicht so.

Die Originaldefinition sieht eigentlich nur so aus (aus himXMLi.pas) und diehnt eigentlich nur der Möglichkeit einer Funktion unterschiedliche Parameter zu übergeben (da keine überladenen Properties möglich sind ... außer in neueren Delphiversionen und da auch nur bei den Default-Properties)
Delphi-Quellcode:
TIndex = Record
  ValueType:  (vtIntValue, vtStringValue);
  IntValue:   Integer;
  StringValue: String;
  Class Operator Implicit(      Value: Integer): TIndex;
  Class Operator Implicit(Const Value: String): TIndex;
End;
Intern wird da der übergebene Wert direkt entsprechend behandelt.

Also es kommt dann auf die Interne Behandlung an, also ob der Typ sich auch mal ändern kann und man eventuell sogar eine Typumwandlug mit integriert hat,
oder ob der Typ danach Fest ist.

BAMatze 15. Jun 2009 14:44

Re: Änderung einer Deklarartion integer <-> double mög
 
Also habe das jetzt erstmal wie folgt gelöst:

Delphi-Quellcode:
type TZahltyp = (ZtGanzzahl, ZtposGanzzahl, ZtGleitkommazahl, ZtposGleitkommazahl);

Type TLabZahlEdit = Class(TWinControl)
  private
    ...
    FvValue: Variant;
    ...
    procedure SetValue(vWert: Variant);
    function GetValue: Variant;
  protected
    ...
  published
    ...
    property Value: Variant read GetValue write SetValue;
  public
    ...
end;

procedure TLabZahlEdit.SetValue(vWert: Variant);
var sTemp: string;
    dTemp: double;
    iTemp: integer;
begin
  // es muss bei der Konvertierung darauf geachtet werden, dass ein int auch in
  // ein double umgewandelt werden kann und somit muss anhand des eingestellten
  // Zahlentyps die richtige Konvertierung durchgeführt werden.
  sTemp := vartostr(vWert);
  if sTemp <> Null then
    begin
      case FEdEingabe.Zahlart of
        Ganzzahl: if trystrtoint(sTemp, iTemp) then
                             begin
                               FvValue := vWert;
                               SetText(sTemp);
                             end;
        posGanzzahl: if trystrtoint(sTemp, iTemp) then
                             begin
                               FvValue := vWert;
                               SetText(sTemp);
                             end;
        Gleitkommazahl: if trystrtofloat(sTemp, dTemp) then
                             begin
                               FvValue := vWert;
                               SetText(sTemp);
                             end;
        posGleitkommazahl: if trystrtofloat(sTemp, dTemp) then
                             begin
                               FvValue := vWert;
                               SetText(sTemp);
                             end;
      end;
    end;
end;

function TLabZahlEdit.GetValue: Variant;
var sTemp: string;
    iTemp: integer;
    dTemp: double;
begin
  sTemp := vartostr(FvValue);
  case FEdEingabe.Zahlart of
    Ganzzahl: if trystrtoint(sTemp, iTemp) then result := strtoint(sTemp);
    posGanzzahl: if trystrtoint(sTemp, iTemp) then result := strtoint(sTemp);
    Gleitkommazahl: if trystrtofloat(sTemp, dTemp) then result := strtofloat(sTemp);
    posGleitkommazahl: if trystrtofloat(sTemp, dTemp) then FvValue := strtofloat(sTemp);
  end;
end;
Könnt ihr euch ja vieleicht mal anschauen, ob ich da jetzt einen Denkfehler drin hab oder ob das ok ist. Danke euch auf jeden Fall für eure Anregungen.

MfG
BAMatze

himitsu 15. Jun 2009 14:52

Re: Änderung einer Deklarartion integer <-> double mög
 
Zitat:

Delphi-Quellcode:
if sTemp <> Null then

sTemp ist immer ungleich NULL , selbst wenn es "leer" ist.
Wenn schon, dann solltest du vWert auf NULL prüfen.

BAMatze 15. Jun 2009 15:10

Re: Änderung einer Deklarartion integer <-> double mög
 
Zitat:

Zitat von himitsu
Zitat:

Delphi-Quellcode:
if sTemp <> Null then

sTemp ist immer ungleich NULL , selbst wenn es "leer" ist.
Wenn schon, dann solltest du vWert auf NULL prüfen.

Arbeite ich gleich mit ein, Danke @himitsu

quendolineDD 15. Jun 2009 15:25

Re: Änderung einer Deklarartion integer <-> double mög
 
Ebenso könnte man den Quelltext etwas verschlanken. In dem Case machst du nach dem TryStrToXXX immer das gleiche.

BAMatze 15. Jun 2009 18:04

Re: Änderung einer Deklarartion integer <-> double mög
 
Zitat:

Zitat von quendolineDD
Ebenso könnte man den Quelltext etwas verschlanken. In dem Case machst du nach dem TryStrToXXX immer das gleiche.

ja hab ich auch schon drüber nachgedacht. Werde ich dann morgen mal machen, danke auch an dich.

shmia 15. Jun 2009 18:26

Re: Änderung einer Deklarartion integer <-> double mög
 
Das scheint mir doch alles etwas zu aufwändig zu sein.
In einem TEdit (und alles was davon abgeleitet ist), steht in erster Linie ein Text.
Möchte man sich das Leben etwas einfacher machen, dann kann man zusätzliche Properties aufnehmen:
Delphi-Quellcode:
Property Text:String;
property AsFloat:Extended read ... write ...;
property AsInteger:Integer read ... write ...;
Der Anwender der Komponente hat doch fast immer eine genaue Vorstellung was in dem Control drinsteckt (ganzzahl, float, Text) und wählt das passende Property.


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