|
Registriert seit: 8. Jun 2009 Ort: Bayern 1.153 Beiträge Delphi 11 Alexandria |
#1
Was ich benötige: Einen äußerst flexiblen INI-Datei-Editor mit einer Prüfung, ob die Benutzerdaten korrekt sind.
Ein Delphi-Formular mit entsprechenden GUI-Komponenten wäre mir viel zu statisch. Hier ist das Ergebnis nach ca. 2 Stunden Arbeit mit ChatGPT: In der ersten Version waren die GUI und die Nutzerlogik untrennbar miteinander verbunden. In den folgenden Iterationen habe ich schließlich diese Klasse entwickelt. Ich freue mich über Feedback!
Delphi-Quellcode:
unit StudyDatamodule;
interface uses System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants, Rtti, TypInfo, Math, FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.Memo.Types, FMX.StdCtrls, FMX.Controls.Presentation, FMX.ScrollBox, FMX.Memo, Unit_Tdatamodule, FMX.Edit; type TForm1 = class(TForm) mmo1: TMemo; btn_InitLIst: TButton; edt_propertyValue: TEdit; lbl_PropertyName: TLabel; btn_Up: TButton; btn_Down: TButton; edt_Datatype: TEdit; btn_ListasJSON: TButton; procedure FormCreate(Sender: TObject); procedure btn_UpClick(Sender: TObject); procedure btn_DownClick(Sender: TObject); procedure edt_propertyValueEnter(Sender: TObject); procedure edt_propertyValueExit(Sender: TObject); procedure edt_propertyValueKeyDown(Sender: TObject; var Key: Word; var KeyChar: Char; Shift: TShiftState); procedure edt_propertyValueKeyUp(Sender: TObject; var Key: Word; var KeyChar: Char; Shift: TShiftState); procedure btn_ListasJSONClick(Sender: TObject); private { Private declarations } FDataItemList: TDataItemList; FItemIndex: Integer; procedure DisplayActiveItem(index: Integer); procedure SaveInputToItem; function ValidateInput(const Value: string; DataType: TInputType): Boolean; public { Public declarations } end; var Form1: TForm1; implementation {$R *.fmx} // Example Initialization from StringList // ere’s an updated FormCreate method that uses the new functionality: procedure TForm1.btn_DownClick(Sender: TObject); begin FItemIndex := FItemIndex - 1; FItemIndex := Max(FItemIndex, 0); DisplayActiveItem(FItemIndex); end; procedure TForm1.btn_ListasJSONClick(Sender: TObject); begin mmo1.Lines.Add(FDataItemList.AsJSON); end; procedure TForm1.btn_UpClick(Sender: TObject); begin FItemIndex := FItemIndex + 1; FItemIndex := Min(FItemIndex, FDataItemList.Count - 1); DisplayActiveItem(FItemIndex); end; procedure TForm1.DisplayActiveItem(index: Integer); var DataItem: TDataItem; begin DataItem := FDataItemList.Items[Index]; lbl_PropertyName.Text := DataItem.Name; edt_propertyValue.Text := DataItem.Value; edt_Datatype.Text := GetEnumName(TypeInfo(TInputType), Integer(DataItem.DataType)); end; procedure TForm1.edt_propertyValueEnter(Sender: TObject); begin /// check for valid user inputs and save data end; procedure TForm1.edt_propertyValueExit(Sender: TObject); begin SaveInputToItem; end; // Restrict input while typing procedure TForm1.edt_propertyValueKeyDown(Sender: TObject; var Key: Word; var KeyChar: Char; Shift: TShiftState); var DataItem: TDataItem; begin if (FItemIndex < 0) or (FItemIndex >= FDataItemList.Count) then Exit; DataItem := FDataItemList.Items[FItemIndex]; // Restrict input for numbers and booleans case DataItem.DataType of itNumber: if not(KeyChar in ['0' .. '9', '.', '-', #8]) then // Allow digits, decimal point, negative sign, and backspace KeyChar := #0; itBoolean: if not(KeyChar in ['t', 'r', 'u', 'e', 'f', 'a', 'l', 's', #8]) then // Allow 'true' and 'false' KeyChar := #0; end; end; procedure TForm1.edt_propertyValueKeyUp(Sender: TObject; var Key: Word; var KeyChar: Char; Shift: TShiftState); begin end; // Save the user's input into the active data item procedure TForm1.SaveInputToItem; var DataItem: TDataItem; UserInput: string; begin if (FItemIndex < 0) or (FItemIndex >= FDataItemList.Count) then Exit; DataItem := FDataItemList.Items[FItemIndex]; UserInput := Trim(edt_propertyValue.Text); // Validate the input if not ValidateInput(UserInput, DataItem.DataType) then begin ShowMessage(Format('Invalid input for %s. Expected a %s value.', [DataItem.Name, GetEnumName(TypeInfo(TInputType), Integer(DataItem.DataType))])); edt_propertyValue.SetFocus; // Return focus to the input field Exit; end; // Save the validated input to the data item's Value field DataItem.Value := UserInput; end; // Validate user input based on the data type of the current item function TForm1.ValidateInput(const Value: string; DataType: TInputType): Boolean; var TempFloat: Double; TempBoolean: Boolean; begin Result := False; case DataType of itString: Result := True; // Any string is valid itNumber: Result := TryStrToFloat(Value, TempFloat); // Validate numeric input itBoolean: Result := TryStrToBool(Value, TempBoolean); // Validate boolean input ('true' or 'false') end; end; procedure TForm1.FormCreate(Sender: TObject); var StringList: TStringList; DataItem: TDataItem; begin StringList := TStringList.Create; FDataItemList := TDataItemList.Create(True); // Owns objects try // Populate TStringList with data using '|' as the delimiter StringList.Add('EnableLogging|Boolean|true'); StringList.Add('MaxLogFileSize|Number|1048576'); // File size in bytes (1 MB) StringList.Add('LogFilePath|String|C:\Logs\app.log'); StringList.Add('EnableAutoSave|Boolean|true'); StringList.Add('AutoSaveInterval|Number|10'); // Interval in minutes StringList.Add('Theme|String|dark'); StringList.Add('ShowNotifications|Boolean|true'); StringList.Add('MaxRetries|Number|3'); StringList.Add('RetryDelay|Number|5'); // Delay in seconds StringList.Add('EnableEncryption|Boolean|true'); StringList.Add('EncryptionKey|String|default_key'); StringList.Add('AllowGuestAccess|Boolean|false'); StringList.Add('DefaultLanguage|String|en'); StringList.Add('TimeoutDuration|Number|30'); // Timeout in seconds StringList.Add('EnableDebugMode|Boolean|false'); FDataItemList.LoadFromStringList(StringList); // Load data into TDataItemList FDataItemList.LoadFromStringList(StringList); // Display loaded items for verification for DataItem in FDataItemList do mmo1.Lines.Add(Format('Name: %s, DataType: %s, DefaultValue: %s', [DataItem.Name, GetEnumName(TypeInfo(TInputType), Integer(DataItem.DataType)), DataItem.DefaultValue])); DisplayActiveItem(FItemIndex); finally StringList.Free; end; end; end. und die Klasse zur Datenspeicherung
Delphi-Quellcode:
unit Unit_TDataModule; interface uses System.Classes, System.SysUtils, System.Generics.Collections, System.JSON, System.IOUtils, TypInfo; type // Enum to represent input types TInputType = (itString, itNumber, itBoolean); // Class representing individual data items TDataItem = class private FName: string; FDataType: TInputType; FValue: string; FDefaultValue: string; public property Name: string read FName write FName; property DataType: TInputType read FDataType write FDataType; property Value: string read FValue write FValue; property DefaultValue: string read FDefaultValue write FDefaultValue; constructor Create(const AName: string; ADataType: TInputType; const ADefaultValue: string); overload; procedure ResetToDefault; // Resets the Value to DefaultValue end; // Class representing a list of data items TDataItemList = class(TObjectList<TDataItem>) private function GetAsJSON: string; // Returns JSON representation of the list public property AsJSON: string read GetAsJSON; // Read-only property to get JSON string procedure LoadFromStringList(AStringList: TStringList); // Load items from a string list procedure SaveToFile(const AFileName: string); // Save items to a JSON file procedure LoadFromFile(const AFileName: string); // Load items from a JSON file end; implementation { TDataItem } constructor TDataItem.Create(const AName: string; ADataType: TInputType; const ADefaultValue: string); begin inherited Create; FName := AName; FDataType := ADataType; FDefaultValue := ADefaultValue; FValue := ''; // Initialize Value to unset (empty string) end; procedure TDataItem.ResetToDefault; begin FValue := FDefaultValue; // Reset Value to the DefaultValue end; { TDataItemList } function TDataItemList.GetAsJSON: string; var JSONArray: TJSONArray; JSONObject: TJSONObject; DataItem: TDataItem; begin JSONArray := TJSONArray.Create; try // Iterate through the items and convert them to JSON for DataItem in Self do begin JSONObject := TJSONObject.Create; JSONObject.AddPair('Name', DataItem.Name); JSONObject.AddPair('DataType', GetEnumName(TypeInfo(TInputType), Integer(DataItem.DataType))); // Convert enum to string JSONObject.AddPair('Value', DataItem.Value); JSONObject.AddPair('DefaultValue', DataItem.DefaultValue); JSONArray.AddElement(JSONObject); end; Result := JSONArray.ToJSON; // Return the JSON string finally JSONArray.Free; end; end; procedure TDataItemList.LoadFromStringList(AStringList: TStringList); var i: Integer; LineParts: TArray<string>; Name, DefaultValue: string; DataType: TInputType; function ParseDataType(const DataTypeStr: string): TInputType; begin if SameText(DataTypeStr, 'Boolean') then Result := itBoolean else if SameText(DataTypeStr, 'Number') then Result := itNumber else if SameText(DataTypeStr, 'String') then Result := itString else raise Exception.CreateFmt('Unknown data type: %s', [DataTypeStr]); end; begin for i := 0 to AStringList.Count - 1 do begin LineParts := AStringList[i].Split(['|']); if Length(LineParts) <> 3 then raise Exception.CreateFmt('Invalid format in line %d: %s', [i + 1, AStringList[i]]); Name := LineParts[0]; DataType := ParseDataType(LineParts[1]); DefaultValue := LineParts[2]; // Add the item and set both DefaultValue and Value Self.Add(TDataItem.Create(Name, DataType, DefaultValue)); Self.Last.Value := DefaultValue; // Initialize Value to DefaultValue end; end; procedure TDataItemList.SaveToFile(const AFileName: string); begin // Save the JSON representation to a file TFile.WriteAllText(AFileName, AsJSON); end; procedure TDataItemList.LoadFromFile(const AFileName: string); var JSONArray: TJSONArray; JSONObject: TJSONObject; JSONString: string; i: Integer; Name, DataTypeStr, Value, DefaultValue: string; DataType: TInputType; function ParseDataType(const DataTypeStr: string): TInputType; begin if SameText(DataTypeStr, 'itBoolean') then Result := itBoolean else if SameText(DataTypeStr, 'itNumber') then Result := itNumber else if SameText(DataTypeStr, 'itString') then Result := itString else raise Exception.CreateFmt('Unknown data type: %s', [DataTypeStr]); end; begin // Load JSON string from file JSONString := TFile.ReadAllText(AFileName); // Parse JSON string JSONArray := TJSONObject.ParseJSONValue(JSONString) as TJSONArray; if not Assigned(JSONArray) then raise Exception.Create('Invalid JSON format in file.'); try // Iterate through JSON array and populate the list for i := 0 to JSONArray.Count - 1 do begin JSONObject := JSONArray.Items[i] as TJSONObject; Name := JSONObject.GetValue<string>('Name'); DataTypeStr := JSONObject.GetValue<string>('DataType'); Value := JSONObject.GetValue<string>('Value'); DefaultValue := JSONObject.GetValue<string>('DefaultValue'); DataType := ParseDataType(DataTypeStr); // Add the item Self.Add(TDataItem.Create(Name, DataType, DefaultValue)); Self.Last.Value := Value; // Set the current value end; finally JSONArray.Free; end; end; end. |
![]() |
Ansicht |
![]() |
![]() |
![]() |
ForumregelnEs ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.
BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus. Trackbacks are an
Pingbacks are an
Refbacks are aus
|
|
Nützliche Links |
Heutige Beiträge |
Sitemap |
Suchen |
Code-Library |
Wer ist online |
Alle Foren als gelesen markieren |
Gehe zu... |
LinkBack |
![]() |
![]() |