Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Varios (https://www.clubdelphi.com/foros/forumdisplay.php?f=11)
-   -   Problemas con MDI y Bases de datos (https://www.clubdelphi.com/foros/showthread.php?t=4399)

NeWsP 14-10-2003 20:41:56

Problemas con MDI y Bases de datos
 
Buenas Noches, Este es mi primer Post en este foro, aunque llevo algun tiempo navegando por el, y viendo buenos resultados, asi que espero q me podais hechar una mano :)

Mi problema es el siguiente con el mdi:

1 - Tengo un Formulario padre , que al pulsar un boton aparece el hijo, que contiene un DBGRID entre otras cosas. Cuando en este formulario hijo pulso el boton "AÑADIR" se abre otro formulario ( NORMAL , ni hijo ni nada ) con una serie de campos para introducir los datos en la base de datos. cuando le doy al boton de INSERTAR DATOS , me da un error de memoria, el boton esta puesto asi

Form2.dbgrid1.ReadOnly := false;
Form2.table1.insert;
Form2.table1.FieldByName('Talleres').assString := Edit1.Text
Form2.table1.post;
Form2.dbgrid1.ReadOnly := true;

lo que no entiendo es pq si hago esa misma aplicacion sin formularios hijos ni padres, y estando el dbgrid en el Form1 si que funciona :(

Espero que me podais ayudar, estoy un poco desesperado ya.

Muchas Gracias

NeWsP

__cadetill 14-10-2003 20:52:13

Si debugeas la aplicación, en que linea exacta te salta la excepción? Qué clase de excepción es?

Un apunte. No son necesarias las lineas de ReadOnly a true/false
Otro apunte. Es mejor tener los Datasets en un DataModule para facilitar el acceso a ellos desde cualquier formulario y tenerlos bien localizados y agrupados

roman 14-10-2003 20:53:59

Me suena a que Form2 es el formulario que te da Delphi por default y no el que creas en código. Posiblemente Form2 no esté en el "Autocreate" y de ahí que no puedas acceder a él. Asegúrate de que en INSERTAR DATOS te refieras no al formulario que te da Delphi sino al que tú mismo creas.

// Saludos

NeWsP 14-10-2003 21:09:06

Gracias a los dos por contestar tan pronto :)

cadetill el error me lo da en todas las lineas del form3 ( el de insertar datos ) q tienen referencia al form2 y me da error de memoria violation adrees .....

roman , io el formulario hijo lo creo asi :

procedure Tform1.CrearHijo()
var
hijo : TForm2;
begin
hijo:= TForm2.Create(Application);
end;

CrearHijo();

asi es como creo el hijo.

E comprado sustituyendo el form2 de las lineas de antes por 'hijo' pero me dice q no esta declarado :(

alguna sugerencia please :)

guillotmarc 14-10-2003 21:18:39

Hola.

Al crear los formularios de esta forma no puedes usar las variables Form1, Form2, ... (Además esas variables no son nada recomendables en aplicaciones como las MDI en que puedes tener más de un formulario del mismo tipo cargados en pantalla).

El problema de utilizar la variable Hijo es que donde la has declarado, solo existe durante la ejecución de CrearHijo.

Deberías declarar la variable en un ámbito superior, para que se pueda usar en cualquier lugar del ámbito. Por ejemplo, en la sección Private del formulario que lo llama, o directamente en el modulo del Formulario, ...

Aunque personalmente no me gustan mucho este tipo de variables pseudo-globales, y solo las utilizo cuando són estrictamente imprescindibles.

En tu caso, por ejemplo, si el código que da el error está en el mismo formulario, no hace falta que especifiques el formulario (se asume por defecto la instancia que se está ejecutando).

Es decir cambia el código por :

dbgrid1.ReadOnly := false;
table1.insert;
table1.FieldByName('Talleres').assString := Edit1.Text
table1.post;
dbgrid1.ReadOnly := true;

Saludos.

NeWsP 14-10-2003 21:22:48

Ok, Gracias :)

Ahora probare , la funciona la tengo declarada tb en privare , pero no la variable.

Espero tener suerte. :)

por cierto si q tengo q poner el nombre del form donde esta pq es diferente el form donde se introducen los datos y donde esta la table :)

gracias por todo.

roman 14-10-2003 21:27:02

Además de lo que ya te explicó marcguillot yo pensaría en la siguiente solución:

En Form3 declaras una propiedad pública de tipo TForm2:

Código:

type
  TForm3 = class
  public
    GridForm: TForm2;
  end;

En Form2, en el botón de "AÑADIR", muestras Form3 así:

Código:

  with TForm3.Create(nil) do
    GridForm := Self;
    ShowModal;
    Free;
  end;

y las referencias al formulario con el grid dentro de Form3 las haces con FormGrid, p. ej:

FormGrid.Table1.Insert;

// Saludos

guillotmarc 14-10-2003 21:46:27

Hola.

La verdad es que siempre me ha parecido increible que los componentes de un formulario esten declarados en una sección pública que permite a otros formularios acceder a ellos.

En mi opinión un formulario nunca deberia poder acceder a los componentes de otros (quizá en algún caso muy concreto pueda ser adecuado, pero no se me ocurre ninguno).

Lo correcto, a mi modo de ver, es declarar una función Insertar en el formulario, y que los otros formularios accedan a esa función y no a los componentes.

Código:

type
  TForm2 = class(TForm)
  ...
  ...
  public
    procedure AnadirValor(Texto: String);
  ...
  ...

implementation
 
  procedure TForm2.AnadirValor(Texto: String);
  begin
    dbgrid1.ReadOnly := false;
    table1.insert;
    table1.FieldByName('Talleres').assString := Edit1.Text
    table1.post;
    dbgrid1.ReadOnly := true;
  end;

Ahora para ejecutar esa acción, podemos hacer desde otro Formulario :

Hijo.AnadirValor(Edit1.Text);

Aunque si vas a utilizar una variable Hijo, ten en cuenta que ocurrirá cuando tengas abiertas dos veces un formulario de ese tipo. La variable Hijo solo te apuntará a una de ellas. (¿ cual será ?, ¿ la ultima abierta ?, debes tenerlo controlado). La propuesta de Roman, es un buen ejemplo en el que se tiene controlado el formulario hijo, aunque puede haber varios de ellos.

Saludos.

NeWsP 14-10-2003 21:58:23

Gracias otra vez a los dos.

Solo tengo un problemilla mas ( es de tontos ... ) pero no me entra... , al escribir esto :

type
TForm3 = class
public
GridForm: TForm2;
end

me dice q TForm2 no esta declarado, en cambio si q le digo q use el Unit2 pero se lo digo mas tarde...

aunque la forma de Guillotmarc tb la veo muy interesante, sera question de probarla :)

roman 14-10-2003 22:14:44

En realidad lo que dice guillotmarc acerca de la "publicidad" de las componentes de un formulario es completamente cierto y sólo lleva a malas prácticas de programación que posteriormente dan dolores e cabeza.

Si un formulario tiene un Edit edtTalleres, la propiedad pública debiera ser el texto del control y no el control mismo.

En el caso concreto que nos ocupa entiendo lo siguiente:

Un formulario contiene una rejilla para visualizar los datos pero en lugar de editar éstos en la misma rejilla se desea abrir un formulario de captura, situación por demás normal ya que en muchas ocasiones la rejillasólo muestra unos cuantos de los campos a fin de que el usuario los pueda identificar.

Ahora bien, "normalmente", el forumulario de captura de datos contiene componente TDBEdit en lugar de simples TEdit (como en el presente caso) y dichos TDBEdit (u otros controles DB) están ligados a componentes DataSource localizados en un módulo de datos, como indica cadetill

Aunque de alguna manera también así accedemos a los controles de otro módulo (el datasource), en este caso, un módulo de datos, me parece apropiado y hasta necesario (¿de qué otra forma hacemos el enlace?)

Pero si por las razones que fueren, se insiste o se deben utilizar TEdits normales entonces lo más correcto, desde mi punto de vsta, sería, como mencioné arriba, publicar el texto de dichos controles:

Código:

type
  TForm3 = class(TForm)
  private
    function GetTalleres: String;
    procedure SetTalleres(Value: String);
  public
    property Talleres: String read GetTalleres write SetTalleres;
  end;

implementation
  function TForm3.GetTalleres: String;
  begin
    Result :=edtTalleres.Text;
  end;

  procedure TForm3.SetTalleres(Value: String);
  begin
    edtTalleres.Text := Value;
  end;
end.

De esta forma, cuando desde el formulario con la rejilla deseemos editar los datos de un registro pondríamos:

Código:

with TForm.Create(nil) do
begin
  Talleres := Table1.FieldByName('Talleres').AsString;
  { Otros campos }
 
  if ShowModal = ID_OK then
  begin
    Table1.FieldByName('Talleres').AsString := Talleres;
    { Otros campos }
    Table1.Post;
  end;

  Free;
end;

Así, el formulario con la rejilla usa del formulario de datos lo único que debe saber: sus datos; y no sus controles.

// Saludos

roman 14-10-2003 22:17:48

Cita:

Posteado originalmente por NeWsP
[...]al escribir esto :

type
TForm3 = class
public
GridForm: TForm2;
end

me dice q TForm2 no esta declarado, en cambio si q le digo q use el Unit2 pero se lo digo mas tarde[...]

Deberás poner el unit2 en la parte de la "interface" mienras que en Unit2 deberás poner el unit3 en la parte de "implementation"

// Saludos


La franja horaria es GMT +2. Ahora son las 12:37:07.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi