Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Die Delphi-IDE (https://www.delphipraxis.net/62-die-delphi-ide/)
-   -   Frames (https://www.delphipraxis.net/195194-frames.html)

Walter Landwehr 10. Feb 2018 16:21

Frames
 
Hallo,

ich habe ein Frame das ich zur Laufzeit in ein Formular einbinde. Dies funktioniert auch.
In dem Frame gibt es eine Query. Nun will ich einen neuen Datensatz einfügen bekomme aber die in dieser Procedere eine Zugriffsverletzung.

Delphi-Quellcode:
procedure TframeSpenden.qryMitgliederspendenNewRecord(DataSet: TDataSet);
begin
  qryMitgliederspenden.FieldByName('MITGLIEDERNR').AsInteger := frmMitglieder.MitgliederQry.FieldByName('MITGLIEDERNR').AsInteger;
end;
Irgendwie kann ich nicht auf die MitgliederQry zugreifen, aber warum nicht?

Die Unit Mitglieder habe ich in der Uses hinzugefügt. Was mache ich hier falsch.

Danke für Eure Hilfe.

Redeemer 10. Feb 2018 22:52

AW: Frames
 
Ich halte die Frage für nicht lösbar basierend auf den angegebenen Informationen. Die ist höchstwahrscheinlich nur mit (
Delphi-Quellcode:
interface
-?)Quelltext des Frames und der Form lösbar. FormCreate oder wo auch immer du den Frame erstellst, wäre auch interessant.

In einem ersten Schritt könnte man eine Integervariable anlegen und schauen, ob es an der Quelle oder dem Ziel der Zuweisung liegt.

Walter Landwehr 11. Feb 2018 08:12

AW: Frames
 
OK hier der Code vom Frame
Delphi-Quellcode:
unit Spenden;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes,
  Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, cxGraphics, cxControls,
  cxLookAndFeels, cxLookAndFeelPainters, cxStyles, dxSkinsCore, dxSkinBlack,
  dxSkinBlue, dxSkinBlueprint, dxSkinCaramel, dxSkinCoffee, dxSkinDarkRoom,
  dxSkinDarkSide, dxSkinDevExpressDarkStyle, dxSkinDevExpressStyle, dxSkinFoggy,
  dxSkinGlassOceans, dxSkinHighContrast, dxSkiniMaginary, dxSkinLilian,
  dxSkinLiquidSky, dxSkinLondonLiquidSky, dxSkinMcSkin, dxSkinMetropolis,
  dxSkinMetropolisDark, dxSkinMoneyTwins, dxSkinOffice2007Black,
  dxSkinOffice2007Blue, dxSkinOffice2007Green, dxSkinOffice2007Pink,
  dxSkinOffice2007Silver, dxSkinOffice2010Black, dxSkinOffice2010Blue,
  dxSkinOffice2010Silver, dxSkinOffice2013DarkGray, dxSkinOffice2013LightGray,
  dxSkinOffice2013White, dxSkinOffice2016Colorful, dxSkinOffice2016Dark,
  dxSkinPumpkin, dxSkinSeven, dxSkinSevenClassic, dxSkinSharp, dxSkinSharpPlus,
  dxSkinSilver, dxSkinSpringTime, dxSkinStardust, dxSkinSummer2008,
  dxSkinTheAsphaltWorld, dxSkinsDefaultPainters, dxSkinValentine,
  dxSkinVisualStudio2013Blue, dxSkinVisualStudio2013Dark,
  dxSkinVisualStudio2013Light, dxSkinVS2010, dxSkinWhiteprint,
  dxSkinXmas2008Blue, cxCustomData, cxFilter, cxData, cxDataStorage, cxEdit,
  cxNavigator, cxDataControllerConditionalFormattingRulesManagerDialog, Data.DB,
  cxDBData, cxButtonEdit, cxGridCustomTableView, cxGridTableView,
  cxGridDBTableView, IBODataset, cxGridLevel, cxClasses, cxGridCustomView,
  cxGrid, cxCalendar, cxCurrencyEdit, cxCheckBox;

type
  TframeSpenden = class(TFrame)
    cxGrSpendenView: TcxGridDBTableView;
    cxGrSpendenLevel: TcxGridLevel;
    cxGrSpenden: TcxGrid;
    qryMitgliederspenden: TIBOQuery;
    cxGrSpendenViewDatum: TcxGridDBColumn;
    cxGrSpendenViewSpendenfallnummer: TcxGridDBColumn;
    dsrcMitgliederspenden: TDataSource;
    cxGrSpendenViewSpendennummer: TcxGridDBColumn;
    cxGrSpendenViewSpendenfall: TcxGridDBColumn;
    cxGrSpendenViewBetrag: TcxGridDBColumn;
    cxGrSpendenViewBetraginWorten: TcxGridDBColumn;
    cxGrSpendenViewZuwendung: TcxGridDBColumn;
    cxGrSpendenViewQuittung: TcxGridDBColumn;
    procedure cxGrSpendenViewSpendenfallnummerPropertiesButtonClick(
      Sender: TObject; AButtonIndex: Integer);
    procedure qryMitgliederspendenNewRecord(DataSet: TDataSet);
    procedure qryMitgliederspendenAfterInsert(DataSet: TDataSet);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

implementation

{$R *.dfm}

uses Modul, Main, Mitglieder;

procedure TframeSpenden.cxGrSpendenViewSpendenfallnummerPropertiesButtonClick(
  Sender: TObject; AButtonIndex: Integer);
begin
// Suchen einfügen
end;

procedure TframeSpenden.qryMitgliederspendenAfterInsert(DataSet: TDataSet);
begin
   qryMitgliederspenden.FieldByName('DATUM').AsDateTime := Date;
   qryMitgliederspenden.FieldByName('ZUWENDUNGSART').AsString := 'Geldspende';
end;

procedure TframeSpenden.qryMitgliederspendenNewRecord(DataSet: TDataSet);
begin
  qryMitgliederspenden.FieldByName('MITGLIEDERNR').AsInteger := frmMitglieder.MitgliederQry.FieldByName('MITGLIEDERNR').AsInteger;
end;

end.
Und hier das einbinden in der Form:
Delphi-Quellcode:
  if dmMain.ibqryOptionen.FieldByName('SPENDEN').AsString = 'J' then
  begin
    tshVerein.Caption := 'Spenden';
    tshVerein.Visible := True;
    if not assigned(Spenden)then
    begin
      Spenden := TframeSpenden.Create(PanelVerein);
      Spenden.Parent := PanelVerein;
    end;
    Spenden.BringToFront;
  end;

Delbor 11. Feb 2018 08:15

AW: Frames
 
Hi Walter Landwehr

Datenbankkomponenen und die dazugehörende Logik hat auf einem Frame auch rein gar nichts zu suchen. Eigentlich auch nicht mal auf einer Form, sondern in den meisten Fällen auf einem Datenmodul. Da befinden sich somit auch die gesamten SQL-Statements.
DB-Komponenten können auf einem Formular platziert werden, wenn die Anwendung nicht wirklich viele dieser Dinger braucht. Von Formularen gibt es zur Laufzeit gerade mal dasjenige, das zur Designzeit bearbeitet wurde und somit auch nur eine Instanz der DB-Verbindung.

DB-Komponenten auf Frames zu platzieren, ist hingegen eine sehr schlechte Idee. Vom Basisframe, den du zur Designzeit bearbeitest, siehst du zur Laufzeit gerade mal eine Instanz, die vom Basisfram,e geerbt hat - ob sie auch dessen DB-Verbindung erbt, weiss ich nicht, aber ich könnte mir gut vorstellen: Nein.

Gruss
Delbor

PS:Was soll dieser Code ?:

Delphi-Quellcode:
procedure TframeSpenden.qryMitgliederspendenAfterInsert(DataSet: TDataSet);
begin
   qryMitgliederspenden.FieldByName('DATUM').AsDateTime := Date;
   qryMitgliederspenden.FieldByName('ZUWENDUNGSART').AsString := 'Geldspende';
end;
Das Ereignis AfterInsert ist nicht dazu dda, einer Datenbank etwas hinzuzufügen, sondern um bestimmte Aufgaben ddurchzuführen, nachdem ein Isert stattgefunden hat. So liesse sich zB, eine offee Verbindung gleich wieder schliessen.

Walter Landwehr 11. Feb 2018 08:36

AW: Frames
 
OK Delbor,

das geht natürlich. Das mit dem Datenmodul ist etwas schwierigerer da es sich um MDIForm handelt.

Also lass ich mal die Komponenten auf der Form.

Vielen Dank trotzdem für Deinen Beitrag.

Ghostwalker 11. Feb 2018 08:47

AW: Frames
 
Zitat:

Zitat von Delbor (Beitrag 1393554)
Vom Basisframe, den du zur Designzeit bearbeitest, siehst du zur Laufzeit gerade mal eine Instanz, die vom Basisfram,e geerbt hat - ob sie auch dessen DB-Verbindung erbt, weiss ich nicht, aber ich könnte mir gut vorstellen: Nein.

Falsch, Frames werden, letztlich, genauso gehandhabt wie Forms. Sie lesen die Einstellungen und Komponenten aus einer DFM-Datei (sprich Resource). Der "Große" Unterschied ist, das sie nicht automatisch erzeugt werden und somit nicht automatisch durch Windows bzw. Delphi verwaltet werden.

Ansonsten hast du natürlich recht. Connections, Query's, Tables usw. sollten seperat in einem Datenmodul
erzeugt und gehandelt werden.

@Walter
Ein Datenmodul ist unabhängig von irgendwelchen Forms. Das was du im Designer siehst, ist lediglich ein Platzhalter, das du die entsprechenden Komponenten draufziehen kannst. Aber ein DM zur Laufzeit keine Visualisierung.

Um auf die entsprechenden Komponenten zugreifen zu können. musst du nur die Unit inkludieren und dann via
<Datenmodulname>.<Queryname> zugreifen, egal in welcher Form oder welchen Frame.

Was mir noch auffällt ist, das du versuchst auf ein weiteres Formular (Mitglieder) zu zugreifen. Kann es evtl. sein, das es zu dieser Zeit noch garnicht existiert ?

Delbor 11. Feb 2018 09:47

AW: Frames
 
Hi Ghostwalker
Zitat:

Zitat von Ghostwalker (Beitrag 1393557)
Zitat:

Zitat von Delbor (Beitrag 1393554)
Vom Basisframe, den du zur Designzeit bearbeitest, siehst du zur Laufzeit gerade mal eine Instanz, die vom Basisfram,e geerbt hat - ob sie auch dessen DB-Verbindung erbt, weiss ich nicht, aber ich könnte mir gut vorstellen: Nein.

Falsch, Frames werden, letztlich, genauso gehandhabt wie Forms. Sie lesen die Einstellungen und Komponenten aus einer DFM-Datei (sprich Resource). Der "Große" Unterschied ist, das sie nicht automatisch erzeugt werden und somit nicht automatisch durch Windows bzw. Delphi verwaltet werden.

Sorry, wenn ich dir teilweise wiederspreche:
Ja, Frames werden grundsätzlich sehr ähnlich genauso gehandhabt wie Forms. Aber Frames(Instanzen) können genauso wie Formulare automatisch erstellt oder nur bei Bedarf zur Laufzeit createt werden. Wobei dies immer auf die Frameinstanzen zutrifft, niemals aber auf den Basisframe.. Meine Erfahrungen beim durchsteppen ab der Projektunit:
(Basis-)Frames werden vor der Mainform erstellt. Zumindest, wenn die Mainform oder eine ihr untergeordnete Form ein Frameinstanz enthält, da diese beim konstruieren der Form (Form.OnCreate läuft, zumindest bei den letzten Delphi-Versionen nach dem Constructor der Form ab) die Grundlage zur Erstellung der Frameinstanz(en) darstellen.
Wie das abläuft, wenn zur Entwurfszeit keine Frameinstanzen auf der Form abgelegt sondern dynamisch zur Laufzeit erstellt werde, weiss ich nicht.

Falls du mit 'nicht automatisch erzeugt' darauf anspielst, dass du in der Toolpalette nicht einfach auf 'Frames' klicken und ihn, wie alle andern Komponenten, in eine Form(...) einfügen kannst: einverstanden. Der Frame muss erst über <Datei>Neu>weiter>Frames> erzeugt und definiert werden. Und gerade das ist der Basisframe, den du zur Laufzeit nie zu Gesicht bekommst - was du siehst, sind immer Frameinstanzen.

Es gibt auch noch die Möglichkeit, Frames in der Toolpalette unter einem eigenen Icon abzulegen. Dann dürfte das geschehn, was ich manuell mache: Ein früher mal erstellter Frame wird dem Projekt hinzugefügt, gleichzeitig aber wird eine Instanz dieses Frames auf dem von dir bestimmten Container erstellt.

Gruss
Delbor

arnof 11. Feb 2018 10:06

AW: Frames
 
Zitat:

Zitat von Walter Landwehr (Beitrag 1393540)
Hallo,


Delphi-Quellcode:
procedure TframeSpenden.qryMitgliederspendenNewRecord(DataSet: TDataSet);
begin
  qryMitgliederspenden.FieldByName('MITGLIEDERNR').AsInteger := frmMitglieder.MitgliederQry.FieldByName('MITGLIEDERNR').AsInteger;
end;
Irgendwie kann ich nicht auf die MitgliederQry zugreifen, aber warum nicht?


Danke für Eure Hilfe.

Prüfe als erstes mal, ob das DataSet überhaupt offen ist, sonst kriegst Du genau diese Zugriffverletzung:

Delphi-Quellcode:
procedure TframeSpenden.qryMitgliederspendenNewRecord(DataSet: TDataSet);
begin
 if qryMitgliederspenden.Active then
  qryMitgliederspenden.FieldByName('MITGLIEDERNR').AsInteger := frmMitglieder.MitgliederQry.FieldByName('MITGLIEDERNR').AsInteger;
end;
oder ganz Sicher:

Delphi-Quellcode:
procedure TframeSpenden.qryMitgliederspendenNewRecord(DataSet: TDataSet);
begin
 if Assigned(frmMitglieder) then begin
  if qryMitgliederspenden.Active and frmMitglieder.MitgliederQry.Active then
   qryMitgliederspenden.FieldByName('MITGLIEDERNR').AsInteger := frmMitglieder.MitgliederQry.FieldByName('MITGLIEDERNR').AsInteger;
 end;
end;

Ghostwalker 11. Feb 2018 12:48

AW: Frames
 
Zitat:

Zitat von Delbor (Beitrag 1393563)
Hi Ghostwalker
Zitat:

Zitat von Ghostwalker (Beitrag 1393557)
Zitat:

Zitat von Delbor (Beitrag 1393554)
Vom Basisframe, den du zur Designzeit bearbeitest, siehst du zur Laufzeit gerade mal eine Instanz, die vom Basisfram,e geerbt hat - ob sie auch dessen DB-Verbindung erbt, weiss ich nicht, aber ich könnte mir gut vorstellen: Nein.

Falsch, Frames werden, letztlich, genauso gehandhabt wie Forms. Sie lesen die Einstellungen und Komponenten aus einer DFM-Datei (sprich Resource). Der "Große" Unterschied ist, das sie nicht automatisch erzeugt werden und somit nicht automatisch durch Windows bzw. Delphi verwaltet werden.

Sorry, wenn ich dir teilweise wiederspreche:
Ja, Frames werden grundsätzlich sehr ähnlich genauso gehandhabt wie Forms. Aber Frames(Instanzen) können genauso wie Formulare automatisch erstellt oder nur bei Bedarf zur Laufzeit createt werden. Wobei dies immer auf die Frameinstanzen zutrifft, niemals aber auf den Basisframe.. Meine Erfahrungen beim durchsteppen ab der Projektunit:
(Basis-)Frames werden vor der Mainform erstellt. Zumindest, wenn die Mainform oder eine ihr untergeordnete Form ein Frameinstanz enthält, da diese beim konstruieren der Form (Form.OnCreate läuft, zumindest bei den letzten Delphi-Versionen nach dem Constructor der Form ab) die Grundlage zur Erstellung der Frameinstanz(en) darstellen.
Wie das abläuft, wenn zur Entwurfszeit keine Frameinstanzen auf der Form abgelegt sondern dynamisch zur Laufzeit erstellt werde, weiss ich nicht.

Falls du mit 'nicht automatisch erzeugt' darauf anspielst, dass du in der Toolpalette nicht einfach auf 'Frames' klicken und ihn, wie alle andern Komponenten, in eine Form(...) einfügen kannst: einverstanden. Der Frame muss erst über <Datei>Neu>weiter>Frames> erzeugt und definiert werden. Und gerade das ist der Basisframe, den du zur Laufzeit nie zu Gesicht bekommst - was du siehst, sind immer Frameinstanzen.

Es gibt auch noch die Möglichkeit, Frames in der Toolpalette unter einem eigenen Icon abzulegen. Dann dürfte das geschehn, was ich manuell mache: Ein früher mal erstellter Frame wird dem Projekt hinzugefügt, gleichzeitig aber wird eine Instanz dieses Frames auf dem von dir bestimmten Container erstellt.

Gruss
Delbor

Mit "nicht automatisch erzeugt" meinte ich, das, im Gegensatz zu Formularen, nicht automatisch beim Programmstart eine Instanz erzeugt wird. Ich habs grad mal selbst ausprobiert bei mir :). Wenn du ein Formular erzeugst, wird automatisch eine entsprechende Instanzvariable in der Unit definiert, und diese wird beim Start des Programms automatisch instanziiert. Bei einem Frame bist du als Programmierer selbst dafür verantwortlich entsprechende Instanzen zu erzeugen und auch wieder frei zu geben.

Auch wenn du einen früher erstellten Frame über die Toolpalette dem Projekt hinzufügst, wird noch keine konkrete Instanz erzeugt. Vielmehr wird eine Kopie erzeugt, die als Parent deinen Container hat. Erst wenn du das Programm compilierst und startest, werden die entsprechenden Instanzen erzeugt.

Das man im Falle von DB-Komponenten die Daten der eingestellten Datenbank sieht (zu Designtime) liegt letztlich am Komponenteneditor und der IDE, hat aber nur wenig mit dem zu tun, was zur Laufzeit passiert.

Delbor 11. Feb 2018 15:38

AW: Frames
 
Hi Ghostwalker

Ich sehe schon, wir sprechen vom gleichen und sind uns sehr einig. Das mit der Kopie zur Designzeit habe ich allerdings nicht gewusst. Entweder sagt die Onlinehilfe von Embarcadero nichts darüber aus und spricht immer nur von Frameinstanzen (Frame1, Frame2 etc.), oder ich habs schlicht überlesen.

Das hier finde ich aber trotzdem zumindest alls irritierend:
Zitat:

Bei einem Frame bist du als Programmierer selbst dafür verantwortlich entsprechende Instanzen zu erzeugen und auch wieder frei zu geben.
Alle Objekte, egal ob Tedit oder sonstwas, die selbst erstellt werden, müssen auch selbst freigegeben werden - es sei denn, du weisst einem dynamisch erstellten Objekt gleich die enthaltende Form (die ja nicht zwingend der Parent sein muss; letzters kann ein Panel oder ein anderer Container sein) als Owner zu. Der Owner gibt dann seine untergebenen Objekte frei.
Die Eigenverantwortung des Programmieres beginnt dann, wenn er ein Objekt erstellt und diesem keinen Owner zuweist. So ein Objekt muss zwingend expilizit freigegeben werden.

Gruss
Delbor


Alle Zeitangaben in WEZ +1. Es ist jetzt 11:39 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz