![]() |
dynamisches Erstellen von Oberfläche und Speicherung in DB ?
Hallo @ all,
ich habe eine Sehr große Bitte an euch. Ich muss ein Programm schrieben, dem ich mich im Moment leider nicht gewachsen fühle. :cry: Im Endeffekt soll es eine Art einfache Favoritenliste zum Emails verschicken werden und später noch weiter ausgebaut werden. Man soll nach starten des Programms Reiter und somit weiter Blätter/Oberflächen (,die aber alle gleich sein sollen) dem Formular zufügen können. Im Moment denke ich mir, dass ich das nur mit einer Datenbank lösen kann. Ich habe leider noch nie mit so etwas dynamischen und Datenbanken aus Delphi raus gearbeitet. Deshalb erhoffe ich mir hier von euch ein bisschen Hilfe. Hier mal die Aufgabenstellung, kombiniert mit meinen Gedanken, wie man das Programm angehen könnte: Das Programm soll eine lokale Datenbank (es soll also kein Server laufen) erstellen und diese beim Programmstart immer abfragen. Über einen Menuepunkt (oder Rechtsklick, o.ä.) sollen Reiter (z.B. mit den Komponenten TabContol oder PageControl) erstellt werden können. Beim erstellen der Reiter muss dann auch die Reiterbeschriftung eingegeben werden können. Gleichzeitig soll für jeden angelegten Reiter eine Tabelle angelegt werden. Die Belegung jedes Reiters soll gleich sein und aus 10 Buttons bestehen. Deshalb müssen alle Tabellen auch gleich aufgebaut sein. Die Caption jedes Buttons soll am Anfang z.B. “nicht Belegt“ sein. Über einen Rechtsklick auf den Button möchte ich dann den jeweiligen Button belegen. Heißt, eine Eingabemaske soll aufpoppen und man kann Name, Vorname, und Emailadresse eintragen. Caption des Buttons soll dann z.B. der Name sein. Diese Daten sollen dann in der Datenbank, in der Tabelle des Reiters, in der Zeile des Buttons gespeichert werden. Beim nächsten Aufruf des Programms sollte die Reiter- und Buttonbelegung dann natürlich wieder auftauchen, da er es ja aus der Datenbank lesen sollte. ;) (Ein klick auf einen dieser Buttons soll im späteren Programm dann z.b. über “mailto“ das Empfängerfeld des Standart Email Programms füllen [ist ja kein Problem]) Hoffe ihr habt das so verstanden. Wenn nicht, fragt mir Löcher in den Bauch ;) Ich weiß, dass es schon etwas ziemlich kompaktes und für mich leider sehr schweres ist (was mir im Moment auch leider viele Bauchschmerzen bereitet), hoffe aber trotzdem auf Hilfe/Unterstützung eurerseits, da es vielleicht für den ein oder anderen nur “Kinderkram“ ist. Freue mich über jede Hilfe und jeden Tipp (wie z.B. Wahl der richtigen Datenbank, Lösung des Problems/Anregungen die Dynamik dort rein zu bekommen, u.s.w) Danke schon mal im Vorraus, Berndd [P.S. da ich nicht genau weiss, ob das Thema hier richtig ist, bitte ich einen Mod/Smod/Admin dies zu verschieben, falls es woanders besser passt. Danke] |
Re: dynamisches Erstellen von Oberfläche und Speicherung in
Hi,
also zum einen mal herzlich willkommen in der Delphi-Praxis ;-) Tja, das ist ein ganz schönes Ding. Leider hast Du nicht geschrieben, welche Delphi-Version Du verwendest, also mal zum elementaren: Zur Datenbank: Ohne Datenbankserver wird's schwierig ;-) Zumindest lokal sollte einer laufen. Natürlich gibt es so Sachen wie filebasierte Datenbanken, aber das ist immer ein wenig tricky. Wenn Du z.B. MS Office hast empfehle ich gerne die MSDE (Microsoft SQL Desktop Engine). Das ist der kleine Bruder vom SQL-Server der nicht so viel Performance hat wie der echte und bei 2 Gigabyte Datenbankgröße die Segel streicht, ist aber für Nutzer von MS Office kostenlos und kann alles was das Herz begehrt. Zum Verbinden und damit arbeiten guckst Du nach ![]() Ansonsten ist auch der Griff zu MySQL nicht schlecht, denn die ist klein, ressourcensparend, schnell und gibts im Netz kostenlos ;-) Zur Dynamik: Um dynamische Komponenten anzulegen gibts hier schon ne Menge im Forum. Such einfach mal im Bereich ![]() ![]() Zum Ablauf: Ansonsten würde ich tatsächlich mit einem Formular anfangen und erstmal die Verwaltung der Controls dynamisch machen (erstmal das erzeugen). Im zweiten Schritt würde ich die aktuelle Konfiguration (wiederfinden und 'merken') dann über ein TIniFile machen. Inidateien bieten sich hier an: Du hast eine beliebige Zahl an Reitern (Sections) mit einigen Buttons und deren Values. Du kannst also alle Informationen in einer Ini-Datei strukturiert ablegen. Im dritten Schritt geht man dann hin, liest die Informationen aus dem Inifile aus und baut daraus wieder den Ursprungszustand zusammen. Erst im letzten Schritt würde ich dann hergehen und die Informationen die im Ini-File liegen in die Datenbank zu stecken. Ich denke, so kann man sich vom leichten (dynamische Controls) über die dynamische Organisation von Informationen (Ini-File) bis hin zum Thema Datenbanken durchhangeln. |
Re: dynamisches Erstellen von Oberfläche und Speicherung in
Wie du Komponenten zur Laufzeit erstellst, kannst du hier nachlesen:
![]() Was das Speichern der Einstellungen angeht, halte ich eine Datenbank für übertrieben. Die "modernste" Möglichkeit wäre wohl eine XML-Datei. Dazu findest du auf ![]() [EDIT=Niko]Hm, hätte vielleicht vor dem Schreiben F5 drüchen sollen ... :roll: [/EDIT] |
Re: dynamisches Erstellen von Oberfläche und Speicherung in
Hi.
IMO müssen keine componenten dynamisch erstellt werden, da ja jedes tab gleich aussehen soll. Ein TTabControl, bei dem man anhand des indices entscheidet was man in der tabelle zeigt, würde es auch tun -> spart viel arbeit (imo). Und ne DB für ein paar mail-addys? Ich persöhnlich verwende gerne collections, die dann halt immer komplett im speicher liegt, erst recht seitdem ich einen weg gefunden habe diese auf platte zu streamen (DFM style)! Wenn dich das interessiert dann kannstu hier mal schauen, ob dir das nützt: ![]() Jedes collectionItem wäre dann ein datensatz! Dann machste für jedes tab eine collection-datei und fertig ist die laube :-D cu. |
Re: dynamisches Erstellen von Oberfläche und Speicherung in
borch, erstmal danke euch allen für die netten und kompetenten Antworten.
Da habe ich nun ja einiges erstmal nachzulesen. Zitat:
Naja, aber wenn Enterprise absolut nötig ist, dann denke ich, dass ich sie doch weiter nutzen kann und jemand anderes seine Enterprise gegen Professional tauschen muss. Müsste aber mit beiden Version machbar sein, oder ? Werde mich dann erstmal ein bischen in die vorgeschlagenen Datenbanken und Speicher Varianten einlesen. Sowohl XML, als auch die Streamingvariante hören sich auch sehr interesant an. Muss mich da dann aber erstmal komplett einarbeiten. Es darf lokal allerdings kein Server laufen. MSDE und MySQL brauchen ja nen eigenen Server, oder? Zitat:
Am liebsten würde ich nicht den Umweg über die iniFiles gehen. Aber das wird sich dann noch zeigen, ob ich ohne auf die Schnauze falle. :wink: Habe mich nun auch mit dem dynamischen Erstellen von Komponenten befasst. Kann schon die Buttons in der Laufzeit erstellen. Bekomme es aber leider absolut nicht hin, diese anzusprechen(/ihnen OnClick ereignisse zuzuweisen) oder sie auf die TabControls Komponente zu bringen. Das is schon das nächste Problem, die TabControls Komponente. Wie kann ich bei dieser in der Laufzeit neue Tabs/Reiter erstellen, den einzelnen Tabs Namen zuweisen und die Buttons gleichzeitig drauf platzieren. Zitat:
Kann mir nämlich nicht soooo viel darunter vorstellen :oops: Wäre echt nett von Dir/Euch. Wiedermal Danke im Vorraus, Berndd |
Re: dynamisches Erstellen von Oberfläche und Speicherung in
Hallo,
du sagtest: Zitat:
Jedes TTabControl hab ein onChange event, das ausgelöst wird sobald ein anderes tab angewählt wurde. Dort könntest du dann die daten in die addressliste laden. Du musst nur wissen welche daten, dazu schlage ich vor einen ID-wert in die 'tag'-property jedes, danymisch erstellten, tabs zu schreiben....den du dann als suffix für die dateinamen nimmst. Und als container für die addressdaten sind collectionItems nicht schlecht, da sie eigegebenen daten noch korrigieren können (set methode). Letztendlich musst du das mit dir ausmachen :wink: cu. max. PS: noch besser: ...TTabControl.tabs ist eine stringListe! DH. du könntest jedem tab direkt ein TmxCollection-object anhängen, dann kannst du TTabControl.tabIndex die aktuelle liste rausfinden..oder so. |
Re: dynamisches Erstellen von Oberfläche und Speicherung in
Zitat:
Delphi-Quellcode:
Beim erstellen der Buttons machst Du ja sowas wie:
procedure TForm1.DynButtonClick(sender: TObject);
begin if sender is TButton then begin // hier die Methodik - z.B. Button erkennen end; end;
Delphi-Quellcode:
Der Code ist freilich nicht getestet, sollte aber den Ablauf prinzipiell erklären. Die Methode wird übrigens für _jeden_ Button zugewiesen, d.H. Du musst tatsächlich über den Sender herausfinden, welcher Button gedrückt wurde.
var
myVar: TButton; begin myVar := TButton.Create(self); myVar.Parent := TTabPage1; // der 'Parent' ist die TabPage, auf der der Button erscheinen soll myVar.OnClick := DynButtonClick; // hier die OnClick - Methode. myVar.Name := 'Button'; // anhand des Namens kannst Du oben in der OnClick - Methode den Button identifizieren: ( TButton(sender).Name ) end; Ich würde in Deinem Fall empfehlen, den Button eine Konstante und eine durchlaufende Nummer zu geben. Mit ![]() |
AW: dynamisches Erstellen von Oberfläche und Speicherung in DB ?
Hallo,
ich finde das Thema sehr interessant! Grundsätzliche habe ich aber 2-3 Verständnisfragen: 1. Bei "myVar := TButton.Create(self);" Wie speichere ich "TButton.Create(self)" in der DB ab und wie kann ich das dann nachher aus der DB an myVar zuweisen? 2. Wie kann ich das was eine "OnClick-Procedure oder -Function" machen soll - ebenfalls aus der DB holen und zuweisen? Vielen Dank vorab! Beste Grüße mbulm1 |
AW: dynamisches Erstellen von Oberfläche und Speicherung in DB ?
Ich für meinen Teil mache das schon seit Jahren so in der Art, aber bei mir sind Tabellenfelder immer der Grund dafür, das es bestimmte Controls gibt, text blobs werden als Tmemo erzeugt, varchar als TEdit, Datum als TDateEdit usw.
Alle Infos bekommst du auf dem Weg über die TField Objekte aus einem Dataset, wenn du einfach mit select * from tabelle die Daten holst und dann auf dem offenen Dataset durch fields[i] gehst mit i<fieldcount. Das TField Objekt liefert dir ggf über die Property classname ausreichend Infos, um dann zu entscheiden was kommen soll (für jedes Feld erzeuge ich dann auch noch automatisch ein TLabel als Caption). In der DB hab ich dann in einer tabelle die positionen gespeichert, das sieht dann in etwa so aus
Code:
Beim Erzeugen des Formulars lese ich die Daten aus dem Datenbankfeld Blob Sub_type text die daten in eine TStringlist und über Feldname und Komponenten Präfix such ich mir aus der TStringlist mit Values dann die Werte raus, die mein Code zum jeweiligen Feld bereits kennt (Meinen Eintrag .HILFE kann man zB. im Hint oder in einer Statusbar anzeigen, die kann der Endkunde selber ergänzen).
cbxARCLADEN_CB.LEFT=178
cbxARCLADEN_CB.TOP=950 cbxARCLADEN_CB.WIDTH=26 cedARBEITSGANG_POSDIFF.HILFE=leeres Feld = Ag an letzter Stelle , -1 = AG an vorletzter Stelle etc. cedARBEITSGANG_POSDIFF.LEFT=439 cedARBEITSGANG_POSDIFF.TOP=438 cedARBEITSGANG_POSDIFF.WIDTH=56 cedAUSLASTUNGMAPROZ.HILFE=Zu wieviel % seiner Arbeitszeit ist der AV hier beschäftigt? cedDLZ.HILFE=auf 1 setzen, um neu zu berechnen cedDLZ.LEFT=440 cedDLZ.WIDTH=55 dteBELEGDATUM.LEFT=112 dteBELEGDATUM.TOP=30 dteBESTELLDATUM.LEFT=112 dteBESTELLDATUM.TOP=346 dteLIEFERTERMIN.LEFT=112 dteLIEFERTERMIN.TOP=865 edtAB_CALC.LEFT=113 edtAB_CALC.TOP=731 edtAB_CALC.WIDTH=77 edtANGEBOT_ID_.HILFE=Verknüpfung löschen: Shift + Lupe / leer suchen / leer übernehmen edtANGEBOT_ID_.LEFT=114 edtANGEBOT_ID_.TOP=692 edtANGEBOT_ID_.WIDTH=226 edtARBEITSVORBEREITUNG_ID_.LEFT=112 edtARBEITSVORBEREITUNG_ID_.TOP=318 edtARBEITSVORBEREITUNG_ID_.WIDTH=48 Die Properties kannst du dir ggf. alle durch eine Objektinspektor Komponente anzeigen lassen oder so wie ich das mach, einfach nur some basic functions wie positionieren erlauben (bei meiner Software schaltet der Kunde, sofern berechtigt, die exe in den Designmode, klickt die Felder an, die er neu positionieren möchte (die wechseln dann einfach in background color rot und werden bei onclick in eine TList gepackt. Mit Ctrl+Cursortasten kann er nun left und top aller gewählter Komponenten pixelweise verändern und mit Alt+cursortasten height und width. Wenn er zurück vom Deignmodus in den Normalmodus schaltet, klapper ich auf dem Form alle components[i] bis i<componentcount ab und schreib die mir relevanten eigenschaften zurück die die TStringlist Values und den kompletten inhalt wieder zurück in die DB, so das dann beim nächsten Aufbau des Formulars die position in onshow wieder so legen kann, wie der Kunde das wollte, ohne das ich irgendwas neu compilieren muss. Mein Kunde (der keine Programmierkenntnisse hat) nutz das Verfahren gerne und stellt sich die Formulare damit so um wie er will. Teilweise werden unwichge Felder hinter andere gelegt, man könnte aber auch visible unterstützen etc. Der Vorteil, das über die Datenbankfelder zu machen liegt darin, das du die zum Speichern ggf eh brauchst und ich neue Felder in einer Tabelle ergänzen kann und die sofort beim nächsten Aufruf im Form sind. Wenn die noch keine Positionsdaten in der o.a. TStringlist haben, werden die einfach sequentiell am Ende vom Form angelegt. Taborder läuft bei mir über die Eigenschaft top, also immer von oben nach unten. Von Hand eingetragen werden zum Beispiel Attribute wie Readonly wenn sich die nicht eh schon aus dem TField ergeben und die brauchen eh kein Tabstop. Es hindert dich aber auch niemand dran, einfach mal ein eigenes Format zu entwickeln und dabei dann einfach so was wie Edit1=TEdit Label2=TLabel aus einem Text auszulesen und durch if then else oder andere Konstrukte passende Instanzen zu erstellen (in der TStringlist kannst du mit names[i] finden wie der Eintrag heisst und mit values[i] dann eben sehen, was rechts neben dem gleich steht). wenn der Kram aber auch irgendwo in einer DB gespeichert werden soll muss ggf dein code auch das anpassen oder erstellen der Tabellen mit übernehmen, so das 2 Referenzen zusammen passen müssen. Mein Ansatz ermöglicht es, völlig unterschiedliche Datenmodelle mit der gleichen exe zu öffnen und zu visualisieren, Ich hab meine Exe daher im Prinzip so ähnlich ausgelegt wie ein webbrowser, nur das der eben nicht mit html/http/webserver kommuniziert, sondern direkt mit einer DB. |
AW: dynamisches Erstellen von Oberfläche und Speicherung in DB ?
wenn du mehr auf fertige Komponenten setzen willst, dann schau dir zum Beispiel diese varianten an
![]() ![]() Damit kannst du nahezu alles unbegrenzt zur Laufzeit machen, aber eigentlich ist man dann ganz schnell auf dem Level, das der Anwender der eigenen Software, der diese Features benutzen soll, das gleiche wissen muss wie du selber |
AW: dynamisches Erstellen von Oberfläche und Speicherung in DB ?
Wir haben das damals über den Stream writer gemacht, mit TStream.ReadComponent und TStream.WriteComponent, bei ReadComponent aber drauf achten, dass er die komponenten neu erzeugt, falls du auf dem Formular schon was hast, was standardmässig da ist.
Den Stream dann als Blob in die DB schreiben. Das setzt übrigends auch die events, wenn ich mich recht entsinne (schon 15 Jahre her) |
AW: dynamisches Erstellen von Oberfläche und Speicherung in DB ?
Zitat:
Das kenn ich unter dem Schlagwort: data driven software. Ich habe aber folgenden Frage dazu: Woher bekommst Du denn anschließend die Anwendung dazu? Das Du auf die Art und Weise Felder in die Anwendung bekommst, ist schon klar. Aber was machst Du mit dem Feld dann? Nehmen wir an Du erzeugst ein neues TEdit. Ok. Nun hat der Anwender ein neues Eingabefeld und schreibe da z. B. "Peter" rein. Und nun? Was macht die Software nun mit "Peter"? Wie legst Du diese Information nun beispielsweise in einer DB ab, ohne Dein Programm zu ändern und ohne es neu zu compilieren? Irgendwoher müsste ja nun ein INSERT oder ein UPDATE kommen, der den "Peter" in die DB schreibt - oder? Gruß |
AW: dynamisches Erstellen von Oberfläche und Speicherung in DB ?
Das sind 2 verschiedene Dinge. Das eine ist es die Oberflächenelemente aus einer Datenbank zu Streamen.
Datenbindung ist ja eine andere Baustelle. Hier unterscheidet sich eine Oberfläche, welche sich aus einer DB erzeugt wurde nicht von einer, welche aus einer Ressource der Exe geladen wird. |
AW: dynamisches Erstellen von Oberfläche und Speicherung in DB ?
Hallo Jungs,
ich muss meine Fragen etwas aufteilen - sonst kann ich die Antworten nicht mehr zuordnen! 1. Ihr habt gute Ideen und danke für Eure Hinweise - aber ich habe noch keinen Plan - wie ich zum Beispiel ein "ONCLICK"-Ereignis in der DB abspeichere? Eigentlich muss ich den Quellcode doch vorher schon in einer Procedure ablegen und dann dem Button diese Procedure zuweisen - aber ich muss vorher schon wissen - was der Button machen soll - oder? 2. Gibt es bei Lazarus auch ein TDataset oder was Vergleichbares - ich finde es nicht! 3. Zitat:
Danke vorab! Beste Grüße mbulm1 |
AW: dynamisches Erstellen von Oberfläche und Speicherung in DB ?
Zitat:
|
AW: dynamisches Erstellen von Oberfläche und Speicherung in DB ?
Die Punkte gehören aus meiner Sicht aber schon hier dazu - oder?
Außerdem sehe aktuell NICHTS - wo ich einen Thread erstellen kann!? Warum ist das so? Beste Grüße mbulm1 |
AW: dynamisches Erstellen von Oberfläche und Speicherung in DB ?
Auf Delphi-Praxis klicken (zur Übersicht).
Auf "Sonstige Fragen zu Delphi" klicken. Oben links auf "Neues Thema erstellen" klicken. |
AW: dynamisches Erstellen von Oberfläche und Speicherung in DB ?
[QUOTE=rokli;1414823]
Zitat:
Stellen wir uns vor, wir haben eine einfache Tabelle Mitarbeiter, bestehend aus create table mitarbeiter (ID Int64, Vorname Varchar(80), Nachname Varchar(80), geburtsdatum date) Deine Basis Software, welches die db öffnet, beginnt also einfach mit dem dynamischen erstellen eines Menuitems im Mainmenu oder popupmenu mit der Caption Mitarbeiter, weil es in der DB eine solche Tabelle gibt (in firebird einfach rdb$relations durchsuchen nach Einträgen ohne $ im Namen). Den Menuitem nennst du so wie die Tabelle, nur mit einem prefix, zB mnuMITARBEITER. Der Menuitem bekommt ein Click Event, das für alle anderen dynamisch erzeugten Menuitem dazu auch benutzt wird
Code:
Soweit sollte jeder mit grundlegenden Delphi/Lazarus Kenntnissen das eigentlich hinbekommen. Ich hab mir dabei erlaubt das einfach so runter zu tippen.
var mnu:TMenuItem;
.... begin ... qry.sql.text:='select distinct rdb$relation_name from rdb$relations where rdb$relation_name not containing ''$'''; qry.open; while not qry.eof do begin mnu:=TMenuItem.create(popupmenu1); popupmenu1.items.add(mnu); mnu.name:='mnu'+qry.fields[0].AsString; mnu.caption:=qry.fields[0].AsString; mnu.onclick:=mnuClick; //dafür kannst du ein bereits existierendes click event nehmen oder einfach neu erstellen in gleicher Syntax wie das automatisch erstellte aussehen würde qry.next; end qry.close; end; procedure TForm1.mnuClick(Sender: TObject); var tn:String; begin tn:=copy(TMenuitem(sender).name,4,31); qry.sql.text:='select * from '+tn; qry.open; while not qry.eof do begin //hier kannst du nun für jeden zeile einen eintrag in eine Listbox machen, bei Firebird könntest du dafür eine Computed Feld benutzen, das vorname udn Nachname kombiniert anzeigt //alternativ auch einfach ein datasource angebundenes dbgrid nehmen, das mach ich aber nicht dataObj:=TDataObj.create; dataObj.id:=fields[0].AsInteger; //hier kommt dann später noch mehr in der Erklärung weiter unten bei der Erklärung getDataFromQry dataObj.getDataFromQry; listbox1.items.addObject(dataObj.FullText,dataObj); qry.next; end qry.close; end getDataFromQry macht nun folgendes bei mir (die instanzen der TStringlist werden im Constructor von TDataObj instanziiert) -jedes TDataObj hat eine Eigenschaft fn (fieldnames, als einfach 0 ist ID, 1 ist VORNAME, 2 ist NACHNAME, 3 ist GEBURTSDATUM) und wird gefüllt aus qry.fields[i].Fieldname -jedes TDataObj hat eine Eigenschaft cn (classnames, als einfach 0 ist TIntegerField, 1 ist TStringField, 2 ist TStringField, 3 ist TDateField) und wird gefüllt aus qry.fields[i].classname -jedes TDataObj hat eine Eigenschaft val (values, als einfach 0 ist fields[0].AsString, 1 ist fields[1].AsString, 2 ist fields[2].AsString, 3 ist fields[3].AsString) und wird gefüllt aus qry.fields[i].AsString Damit hast du schon mal unabhängig von den Feldern der Tabelle alles im Speicher und musst nicht mal das dataset offen halten. Ein ListBox.Onlick kann nun folgendes machen
Code:
was macht nun ShowDataOnSbx?
dataObj:=TDataObj(TListbox(sender).objects[TListbox(sender).itemindex]);
dataobj.ShowDataOnSbx(sbx:TScrollBox); Die Anzahl der Felder hast du in dataobj.fn.count, du kannst also in einer Routine ShowDataOnSbx einfach durch alle Feldnamen durchgehen und passend zum Eintrag in cn[i] für das ID Feld ein Label erzeugen (nicht editierbar, weil aus db kommend, meist sogar unsichtbar, für alle TStringFields je ein TEdit und dessen Eigenschaft Text mit dem Inhalt aus val[i] füllen, den Namen zB aus dem prefix edt und dem feldnamen aus fn[i] erzeugen. Bei Geburtsdatum wäre das dann ein TDateEdit mit edt.date:=StrToDate(val[i]); Außerdem erzeuge ich auch automatisch zu jedem Control noch ein TLabel mit der Caption aus FN[i] Die Positionen gehen in Phase 1 einfach von oben nach unten, später dann kommt der beschrieben Designmode dazu und die Positionierung kommt dann eben optional aus der db (siehe oben) Damit hast du nun die Edit felder mit passenden daten gefüllt und nicht nur beim Listbox onclick sondern auch beim navigieren in der Listbox werden die ggf vorhandene Objekte auf der Scrollbox entweder gelöscht und neu erzeugt oder mit sbx.findcomponent gesucht, weil der name ja immer identisch ist innerhalb der gleichen tabellenfelder. Technisch macht eine datasource das nicht viel anders, ist aber auf offene Datasets angewiesen. Nun aber der Haupt Aspekt deiner Frage: Ich änder was und wie geht der Kram wieder zurück in die db? Bei mir bekommen alle editierbaren Controls ein zentrales onchange event, wodurch ich sofort beim editoren weiss, das ich speichern sollte, daher wird in dem moment auch sofort ein Speichern Button enabled. Der Speichern vorgang selber erstellt aus dem Table name und den Feldnamen nur für jeden Tabelle ein sql zusammen, was in etwa wie folgt aussieht
Code:
Wie du den String zusammenbaust sollte dir klar sein,wenn du noch mal FN[i] durchschaust. Damit nix verloren geht wird beim navigate immer gespeichert, wenn
UPDATE OR INSERT INTO MITARBEITER(ID,VORNAME,NACHNAME,GEBURTSDATUM) VALUES (:ID,:VORNAME,:NACHNAME,:GEBURTSDATUM) matching (ID);
der speichern button enabled ist. für jede zeile in FN[] von 0 bis FN.count-1 suchst du nun auf dem sbx mit findcomponent nach dem edt und schreibst das was da drin steht wieder in val[i] Anschliessend bekommt die query die parameter werte in qry.params[i].Value:=val[i] und mit qry.execsql schreibst du das in die DB. für löschen kannst du einfach delete from ... where id=:ID machen und nur den VAL[0] benutzen für neu Anlegen eines Datensatzes erzeugst du ein neues leeres TDataObj, holst dir über eine GetNeueID Methode einen neue unbenutzten Generator Wert und mit dem anschliessenden speichern und erneutem lesen würden auch bereits in der Datenbank existierende Trigger ausgeführt sein und vorgabewerte aus der DB bereits eingetragen sein. Binary Blobs behandel ich sowieso immer anders, aber mit Textblobs geht genau das gleiche Verfahren. Ein Blob Subtype Text erstellen die meisten Queries als TMemoField und beim TMemoField in cn[i] kannst du dann eben ein TMemo als Kompnente benutzen. Das schöne an dem Konzept ist, das du nun mit
Code:
in der Datenbank ein neues Feld anlegen kannst und das beim nächsten Klick auf den o.a. Menuitem schon angezeigt wird, ohne das
alter table mitarbeiter add beruf varchar(40);
du an deiner exe irgendwas anpassen musst. Auch eine neue Tabelle wäre mit dem o.a. Verfahren sofort nach dem Neustart der exe als neuer menuitem verfügbar. Prozesse wie buchen von daten, umwandeln von lieferscheinen in rechnungen, etc. werden bei mir eh immer in der DB realisiert, weil es immer viel schneller ist als im externen client. Das es so einen Prozess gibt, kann man daran umsetzen, das man passende zum tabellen namen einfach Stored procedures in der Datenbank mit entsprechenden Namenskonventionen erzeugt und denen immer nur die ID vom aktuell geöffneten Datensatz als Parameter übergibt, den Rest kann sich die SP dann selber zusammensuchen. Ggf erforderliche zusatzparameter können dynamisch abgefragte Inputparameter in der SP sein, und alle SP, zu denen der Anwender Rechte hat, scheinen eben als Menuitem, oder als Button oder wie auch immer, aber auch alles dynamisch erzeugt. Ein passender name um einen Lieferschein in eine Rechnung zu übernehmen, wäre dabei zum Beispiel der SP Name LIEFERSCHEIN_RECHNUNG udn bei der Anzeige von Lieferscheinen werden für alle SP, die mit LIEFERSCHEIN beginnen, button dynamisch erzeugt. Ob der Lieferschein schon berechnet wurde, ob es einzelrechnungen gibt, einen abweichenden Rechnungsempfänger, oder Sammelrechnungen oder was auch immer, ist nicht Aufgabe vom Front End. Das macht die SP und niemand anders. Das schöne an dem Konzept, mit dem ich seit mittlerweile 7 Jahren eine schon ziemlich komplexe kundenspezifsche Anwendung für mehrere Fertigungsunternehmen, aber auch für den Eigenbedarf erstellt habe, ist, das es relativ egal ist, mit der Front End umgesetzt wird. Delphi egal in welcher Version eignet sich dafür genau so gut wie lazarus und bei den beiden kannst du dafür sogar noch den code parallel benutzen. Mit TMS Webcore geht das auch als Webapplication, könnte aber auf Basis der DB Rules auch direkt mit php, javascript, c# oder sonstwas umgesetzt werden. Die Referenz dafür ist bei mir halt immer die DB und mit Tools wie IEBxpert und Firebird kannst du in der DB auch sehr komplexe Aufgaben lösen und das ganze steht dir trotzdem nicht nur als ein monolithischer Quellcode für alle Kunden zur Verfügung. Jeder Kunde darf selber entscheiden, was er haben möchte und nach entsprechender Einweisung in die DB kann er auch selber Reports erstellen oder anpassen, oder sogar Tabellenfelder ergänzen oder sogar ganz neue Tabellen erstellen, ohne mich dafür fragen zu müssen. und ich muss nicht überlegen, wie ich den ein Formular für alle aufbaue mit dutzende seiten auf Page Controls, damit alle Kunden ihre Wünsche erfüllt bekommen. Komplizierte Events im Front End versuch in zu evrmeiden, aber technisch lassen die sich auch aus der DB mit Hilfe einer der oben genannten Scripting engine realisieren. Customizing Beispiel: Wenn ein Kunde bei jedem Lieferschein spezielle Barcode Etiketten auf ganz bestimmten Druckern in bestimmten Mengen haben möchte, muss ich dafür nicht mal den Quellcode des Frontsends anpassen, sondern erstellen zum Beispiel nur für diesen Kunden in der DB eine Definitionstabelle seine Parameter, einen Trigger, der daraus bei neuen Lieferscheinen einen Job in eigene Jobtabellen erstellt und ein Script zB auf Basis von IBExpert, das dann aus den Jobs in den Tabellen serverseitig die definiterten Printqueus füllt, so das ich mich im Front end auch nicht damit herumärgern muss, ob der nun einen funktionierenden Druckertreiber auch für win7 oder win10 oder sonst was hat ... So, feddich, mal wieder länger geworden, aber ich hoffe das hilft ein wenig zum Verständnis. Wenn Interesse an der Technik besteht, können wir dazu auch gerne Firmenschulungen oder bei ausreichend Interesse auch öffentliche Schulungen anbieten (Meldet euch dafür ggf einfach bei mir hklemt@ibexpert.com) Evtl. mach ich aus dem Front End nach einem Code Cleanup nächstes Jahr auch mal ein Open Source Projekt mit einigen Beispieldatenbanken. Kunden, die bei uns Schulungen machen, können das ggf dann schon ab der Schulung zur weiteren Analyse bekommen. Der Front End ist in Lazarus programmiert, es ist aber eigentlich nichts drin, was nicht auch in Delphi ähnlich umsetzbar ist. |
AW: dynamisches Erstellen von Oberfläche und Speicherung in DB ?
[QUOTE=IBExpert;1415044][QUOTE=rokli;1414823]
Zitat:
DANKE und Beste Grüße mbulm1 |
AW: dynamisches Erstellen von Oberfläche und Speicherung in DB ?
Zitat:
Danke! BG MB |
AW: dynamisches Erstellen von Oberfläche und Speicherung in DB ?
Zitat:
Zitat:
nicht so banal vor, insbesondere unter Debugging Gesichtspunkten kann das im kompletten Chaos enden, weil dir auf dem Weg die Referenzen fehlen, bei denen der delphi oder Lazarus compiler gar nicht erst weitermachen würde (Beispiel: im Text Event kannst du Button1.visible:=false; als code hinterlegen, auch wenn es gar kein button1 mehr gibt. Es knallt dann eben erst wenn der Anwender damit was macht). Events, die sich auf die generelle Bedienung deiner Applikation beziehen, müssen nicht in die DB, ein Event was aber irgendwas mit Datenbankprozessen zu tun hat, sollte einfach ein passendes Objekt in der DB aufrufen werden (zB eine SP) und danach kann dann der Frontend den Screen neu aufbauen, wenn erforderlich. Das Eventchaos üblicher Delphi Anwendungen ist sowieso mit Vorsicht zu genießen, weil sehr schwer im Team zu beherrschen |
Alle Zeitangaben in WEZ +1. Es ist jetzt 04:24 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