Ir al contenido


Foto

Usar function en varios Form?


  • Por favor identifícate para responder
8 respuestas en este tema

#1 dooper

dooper

    Advanced Member

  • Miembros
  • PipPipPip
  • 298 mensajes

Escrito 17 mayo 2016 - 01:23

Pues no hay nada peor, (teniendo en cuanto excepciones a la misma) para tipo novato "obsesionado", tener errores de unidades, y relaciones entre las mismas.
 
Remotándome a hilos del año 2007 (de donde he obtenido en parte una solución) donde algunos de los aquí presentes, eran del tipo anterior mencionado, tarde o temprano me encontraría con estos errores que nunca vienen mal, si la dicha es buena.
 
En ese nostálgico hilo, se decía:

Tienes 2 formas de hacerlo, desde mi punto de vista:
1- Creando una unidad nueva.
- File -> New -> Unit, allí declaras la función y su implementación. Ya es una rutina que no pertenece a ningún Form, pero puedes usarla donde quieras. La Unidad puede llamarse Global.pas, publica.pas, etc. Allí colocas todas las rutinas que sean comunes a varios Forms.
2 - Usando Herencia:
- Creas un Form vacío, le añades la rutina "Habilitar" y lo que debe hacer. Lo llamas BaseForm.Pas
- Al crear una nueva ventana que deba tener esa función "Habilitar", usas File -> new -> other -> projects y ahí debe aparecer "BaseForm", lo seleccionas y le das al botón heredar. La nueva ventana ya dispone del método Habilitar y puedes cambiar su forma de actuar mediante la directiva Override

Este método tiene una ventaja, cualquier ventana que tengas tendrá el método Habilitar, sin importar si es Form3, Form10 o Form32


He usado como principiante que es uno, la primera opción. La 2º se quedará, para cuando pueda entender mas conceptos que ahora pueden ser dificiles de asimilar.
 
-Creo una unidad llamada Unit6Goblal.
-Inserto la función en la unidad Unit6Global tal que así:

delphi
  1. unit Unit6Global;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8. Classes, SysUtils;
  9.  
  10. implementation
  11.  
  12. function GetSexoSeleccionado: string;
  13. begin
  14. Result := RadioGroup1.Items[RadioGroup1.ItemIndex];
  15. end;
  16.  
  17. end

-Indico en el uses de las unidades donde necesito dicha dicha función la unidad Unit6Global.
 
Pero la función tiene un componente RadioGroup  y éste es usado en varias formularios, lo cual me da error de compilación indicándome que no "conoce" este componente en la unidadGlobal, porque está en otras unidades.
Mi primera idea, era indicar en el Uses de la unidad Unit6Global las unidades donde está siendo usado este componente, pero tampoco funciona.
 
Un saludo
  • 0

#2 Agustin Ortu

Agustin Ortu

    Advanced Member

  • Moderadores
  • PipPipPip
  • 831 mensajes
  • LocationArgentina

Escrito 17 mayo 2016 - 01:39

Claro tenes dos problemas:

 

Problema #1: La funcion GetSexoSeleccionado esta declarada en la seccion de implementation. Por lo tanto, es una funcion interna de la unidad. No es exportada. No es visible desde fuera de esa unidad. En programacion, la implementacion se dice que son detalles: es decir, estan, importan, si, pero estan "ocultos"; separados; abstraidos.

 

Se dice que una buena implementacion no deberia dejar que los detalles "escapen", o afloren, es decir, que sea necesario saber como esta implementada la funcionalidad. Todo esto cumpliendo con otro segundo fundamento, y es que la implementacion debe cumplir con el contrato o interface. 

 

La interface es la funcionalidad que se expone; es la manera segura de acceder a la implementacion. La misma interface puede estar implementada de mil maneras distintas, en tanto una implementacion apenas cumple con un contrato

 

Cambiar la implementacion no deberia nunca implicar cambiar la interface. Al cambiar la interface, es muy probable que se tenga que agregar/modificar/eliminar algo de la implementacion

 

Por lo tanto, tu funcion debe estar declarada como exportada en la seccion de interface, e implementada en la seccion de implementacion, asi:


delphi
  1. interface
  2.  
  3. uses
  4. [...]
  5.  
  6. // notar que solo se declara la "cabecera" de los metodos
  7. function NombreDeLaFuncion(const Parametro1: string; const Parametro2: Integer; ... ): Boolean;
  8. procedure NombreDelMetodo(const Parametro1: string; const Parametro2: Boolean);
  9.  
  10. implementation
  11.  
  12. uses
  13. [...]
  14.  
  15. function NombreDeLaFuncion(const Parametro1: string; const Parametro2: Integer; ... ): Boolean;
  16. begin
  17. // implementacion de "NombreDeLaFuncion"
  18. end;
  19.  
  20. procedure NombreDelMetodo(const Parametro1: string; const Parametro2: Boolean);
  21. begin
  22. // implementacion de "NombreDelMetodo"
  23. end;

El problema #2 es que RadioGroup1 es una componente de otro objeto. En la unidad Unit6Global.pas no existe RadioGroup1.

 

Lo mas sencillo es que envies como argumento el TRadioGroup a tu funcion, de esa manera podes acceder al objeto y sus propiedades, asi:


delphi
  1. function GetSexoSeleccionado(ARadioGroup: TRadioGroup): string;
  2. begin
  3. // ahora en lugar de RadioGroup1 usas "ARadioGroup"
  4. end;


  • 1

#3 dooper

dooper

    Advanced Member

  • Miembros
  • PipPipPip
  • 298 mensajes

Escrito 17 mayo 2016 - 02:36

Que buena lección amigo Agustin, solamente las personas iniciadas podemos apreciar lo que podeis aportarnos con estos conceptos.

Probaré a ver que obtengo de tu lección.

 

En cuanto al problema #2, pensaba, que creando la unidad global, sería para solucionar este problema #1, sin introducir parámetros a la función.

Luego para que sirve crear una unidad global con funciones/procedure, si las unidades que necesitan de esas funciones no pueden usarse tal como se llaman, si hay algun componente como en es este caso, y debemos introducir el parametro? normalmente cualquier función o procedure tendrá algun componente que estará o se requiere en otra unidad.

 

TRadioGroup, no lo reconoce en la unidad Unit6Global!!

 

 

Un saludo


  • 0

#4 Agustin Ortu

Agustin Ortu

    Advanced Member

  • Moderadores
  • PipPipPip
  • 831 mensajes
  • LocationArgentina

Escrito 17 mayo 2016 - 03:28

Te hago una pregunta para que reflexiones.. RadioGroup1 es un objeto global?  ;)

 

Lo del uses es porque tenes que incluir en la seccion uses de interface la unidad en donde esta implementado TRadioGroup

 

No te digo el nombre porque en lazarus los paquetes no se llaman igual a los de Delphi


Editado por Agustin Ortu, 17 mayo 2016 - 03:29 .

  • 0

#5 dooper

dooper

    Advanced Member

  • Miembros
  • PipPipPip
  • 298 mensajes

Escrito 18 mayo 2016 - 10:42

Te hago una pregunta para que reflexiones.. RadioGroup1 es un objeto global?  ;)
 
Lo del uses es porque tenes que incluir en la seccion uses de interface la unidad en donde esta implementado TRadioGroup
 
No te digo el nombre porque en lazarus los paquetes no se llaman igual a los de Delphi

 
RadioGroup1 fue y es un componente usado en un Formulario Form3. Ahora tambien quiero usarlo en un Form4.
En el formulario Form3 lo referenciaba con Form3.GetSexoSeleccionado; y todo ok. Pensé inserto la function a nivel "Public" y ha puedo usarla en otro formulario. Ahora viene el problema de tener que hacerlo igualmente en el Form4, pero no me sirve hacer Form3.GetSexoSeleccionado en el formulario form4, porque coge valores el RadioGroup1 que tiene el Form3 y quiero sus valores sean de formulario Form4.
 
Me sigue sin reconocer el componente "TRadioGroup" en la unidad Unit6Global.

delphi
  1. unit Unit6Global;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. Uses Unit3, Unit4; // formularios donde está TRadioGroup ("Hombre", "Mujer")
  8.  
  9. function GetSexoSeleccionado(ARadioGroup: TRadioGroup): string;
  10.  
  11. uses
  12. Classes, SysUtils;
  13.  
  14. implementation
  15.  
  16. function GetSexoSeleccionado(ARadioGroup:TRadioGroup): string;
  17. begin
  18. Result := ARadioGroup.Items[ARadioGroup.ItemIndex];
  19. end;
  20.  
  21. end.


  • 0

#6 Agustin Ortu

Agustin Ortu

    Advanced Member

  • Moderadores
  • PipPipPip
  • 831 mensajes
  • LocationArgentina

Escrito 18 mayo 2016 - 01:23

Lo que seguis sin entender es que el "RadioGroup1" del Form3 es un objeto de TRadioGroup que ni siquiera es primo del "RadioGroup1" del Form4

 

Lo mas importante que tenes que entender es que si bien vos ves "un solo form3" que es el que automaticamente se crea al iniciar la aplicacion, tranquilamente podrias crear otro Form3 que va a ser distinto en el sentido de identidad. Si, va a verse exactamente igual que el anterior, y comportarse de exactamente la misma manera, pero es otro: podria decirse (insultando un poco a la ciencia quizas) que tienen el mismo ADN y lo clonaron; pero son dos tipos distintos, que tienen el mismo molde y se ven igual, pero tuvieron cada cual su historia, su vida

 

Analogamente, el RadioGroup1 por mas que tenga los mismos datos, por mas que se llame igual, todo lo que quieras, son dos distintos.

 

No existe el objeto globlal "RadioGroup1". No hay manera de solucionar tu problema si no es usando parametros para indicar "cual es el RadioGroup1"

 

Todo esto viene de la mano de que los framework que estas usando son orientados a objetos; sin conocer orientacion a objetos, estos conceptos son muy dificiles de asimilar, y pueden ser un baldazo de agua fria. Entiendo que de una u otra manera te estoy diciendo que el sol ahora sale por el otro lado

 

El error que te sale del uses es porque el TRadioGroup no esta implementado en las unidades: Unit3, ni Unit4. No! El RadioGroup esta implementado en el paquete ExtCtrls. Ese es el que debes incluir en el uses. Elimina Unit3 y Unit4


Editado por Agustin Ortu, 18 mayo 2016 - 01:24 .

  • 0

#7 dooper

dooper

    Advanced Member

  • Miembros
  • PipPipPip
  • 298 mensajes

Escrito 18 mayo 2016 - 02:38

Me soprendo. Mi intención fue crear dos formularios iguales, uno para la inserción y otro para la edición. Pero claro "cloné" uno del otro, pensando en que RadioGroup era el mismo componente pero en formularios distintos. Ambos tiene los mismos componentes (TEdit, TRadioGroup.....) pero en Form distintos. La function estaba ubicada en el form insercion, y necesito usarla en el form edicion. Ahí vino el problema al referenciarla en el form edicion (formInsercion.GetSexoSeleccionado), el RadioGroup no funcionaba correctamente en este form, cuando si lo hace bien en el form inserción (donde estaba la función).

 

Como evita estos casos. Porque si una funcion o procedure usa un componente y quiero usarlo en dos formularios distintos, me da estos problemas.este es el caso.

 

Crear la misma funcion en el formulario edicion repetida?....

 

Me "explota" todo por los aires al compilar, no detecta el componente, cargo argumentos y "salta" por otro lado....Deberé agenciarme un "tuto" muy básico para que pueda dominar este caso.

 

 

Un saludo


  • 0

#8 Agustin Ortu

Agustin Ortu

    Advanced Member

  • Moderadores
  • PipPipPip
  • 831 mensajes
  • LocationArgentina

Escrito 18 mayo 2016 - 04:42

Se puede solucionar; pero si te hablo de objetos, de jerarquia de clases, de herencia, de herencia visual (herencia de formularios), de metodos virtuales y abstractos, de redefiniciones de metodos, de polimorfismo...no vas a entender nada, ya que para aprender objetos, te tenes que olvidar de todo lo que estas viendo ahora con el diseñador visual (que hace un monton de trabajo sucio por nosotros), y arrancar por lo mas basico.

 

Hasta que no conozcas todo lo que mencione arriba, no vas a poder evitar repetir codigo (de hecho esta muy bien que te haya llamado la atencion que cierta funcionalidad que ya tenias, porque volver a escribir el mismo codigo? como lo utilizo de nuevo?). El paradigma de objetos nacio para solucionar este problema, su principal objetivo es evitar el codigo duplicado; tener codigo repetido significa que si tu funcion GetSexoSeleccionado cambia, tenes que hacer el mismo cambio en todos los formularios que la implementen

 

Hay una serie de tutoriales del profe Delphius en este foro en la seccion de POO (programacion orientada a objetos)

 

Pero te advierto que es un arte que toma años dominar. La mayoria de la gente vende a la programacion como una ciencia exacta.. todo porque las computadoras entienden binario, y porque tiene cierta cosa "cientifica" en la que uno prueba, investiga, desarrolla e inventa algo.

 

A medida que pasan los años, yo creo que la programacion esta cada vez mas lejos de ser una ciencia (sobre todo la programacion orientada a objetos) y esta mas cerca de ser una filosofia, un arte, una forma de pensar, un paradigma. Lo cual se traduce en que no hay "recetas magicas"; del mismo modo que distintos autores pintan un cuadro y de ninguna manera vas a poder encontrar dos mismos iguales, con los programadores pasa lo mismo. 

 

Asi que no queda otra que transitar este fructifero sendero :)


Editado por Agustin Ortu, 18 mayo 2016 - 04:44 .

  • 1

#9 dooper

dooper

    Advanced Member

  • Miembros
  • PipPipPip
  • 298 mensajes

Escrito 19 mayo 2016 - 12:48

Que gran aporte como siempre Agustín.

 

Luego desde el punto de visto de código, me queda crear una funcion que haga lo mismo que la que tengo pero con un nombre distinto para no repetir su nombre e insertarla en el formulario que quiero que actue, independiente de la original que hace su función en el otro formulario distinto, por lo tanto

dispondría de dos funciones con nombre distintos, con la misma función de codigo, y siendo llamadas en sus respectivos forms.

 

Un saludo


  • 0




IP.Board spam blocked by CleanTalk.