Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Otros temas > Trucos
Registrarse FAQ Miembros Calendario Guía de estilo Buscar Temas de Hoy Marcar Foros Como Leídos

Los mejores trucos

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 24-03-2016
Avatar de jhonny
jhonny jhonny is offline
Jhonny Suárez
 
Registrado: may 2003
Ubicación: Colombia
Posts: 7.058
Poder: 29
jhonny Va camino a la famajhonny Va camino a la fama
Recorrer objetos dentro de un TFMXObject

En Firemonkey, recorrer los objetos que hay dentro de otro es muy sencillo, basta con hacer uso del método EnumObjects que pertenece a la clase TFMXObject... por ejemplo, si queremos saber si existe un TLabel dentro un TTabControl podemos hacerlo de la siguiente manera:

Código Delphi [-]
TabControl1.EnumObjects(
      function (vObjeto: TFMXObject): TEnumProcResult
      begin
        Result := TEnumProcResult.Continue;
        if (vObjeto is TLabel) then
        begin
          ShowMessage('Encontré el Label, ¡victoria!');
          Result := TEnumProcResult.Stop;
        end;
      end
    );

En http://purodelphi.com/2016/03/23/enu...un-tfmxobject/ he creado un artículo con una explicación un poco más extensa de lo que aquí menciono.
__________________
Lecciones de mi Madre. Tema: modificación del comportamiento, "Pará de actuar como tu padre!"

http://www.purodelphi.com/
http://www.nosolodelphi.com/
Responder Con Cita
  #2  
Antiguo 26-03-2016
Avatar de Ñuño Martínez
Ñuño Martínez Ñuño Martínez is offline
Moderador
 
Registrado: jul 2006
Ubicación: Ciudad Catedral, Españistán
Posts: 6.000
Poder: 25
Ñuño Martínez Tiene un aura espectacularÑuño Martínez Tiene un aura espectacular
Buen truco. Estaría bien que Lazarus cambiara en esa dirección también. Ahora mismo sigue la senda de VCL.

Por cierto, un pequeño cambio:

Código Delphi [-]
TabControl1.EnumObjects(
      function (vObjeto: TFMXObject): TEnumProcResult
      begin
        if (vObjeto is TLabel) then
        begin
          ShowMessage('Encontré el Label, ¡victoria!');
          EXIT (TEnumProcResult.Stop)
        end;
        Result := TEnumProcResult.Continue
      end
    );
Parece una tontería, pero será ligeramente más rápido ya que se ahorra una asignación si encuentra un TLabel.

Si se sabe que los TLabel son escasos, se puede optimizar incluso un poco más:

Código Delphi [-]
TabControl1.EnumObjects(
      function (vObjeto: TFMXObject): TEnumProcResult
      begin
        IF NOT (vObjeto IS TLabel) THEN EXIT (TEnumProcResult.Continue);
        ShowMessage('Encontré el Label, ¡victoria!');
        RESULT := TEnumProcResult.Stop
      end
    );
Hoy tengo el día programadoril...
__________________
Proyectos actuales --> Allegro 5 Pascal ¡y Delphi!|MinGRo Game Engine
Responder Con Cita
  #3  
Antiguo 26-03-2016
Avatar de jhonny
jhonny jhonny is offline
Jhonny Suárez
 
Registrado: may 2003
Ubicación: Colombia
Posts: 7.058
Poder: 29
jhonny Va camino a la famajhonny Va camino a la fama
Que bien , me gustan, otra opción para evitar dicha asignación es el típico:

Código Delphi [-]
TabControl1.EnumObjects(
      function (vObjeto: TFMXObject): TEnumProcResult
      begin        
        if (vObjeto is TLabel) then
        begin
          ShowMessage('Encontré el Label, ¡victoria!');
          Result := TEnumProcResult.Stop;
        end
        else
          Result := TEnumProcResult.Continue;
      end
    );

Pero ya que estamos en día programadoril (jejeje vaya día), se me ocurre que podríamos crear un IfThen genérico para estos casos.
__________________
Lecciones de mi Madre. Tema: modificación del comportamiento, "Pará de actuar como tu padre!"

http://www.purodelphi.com/
http://www.nosolodelphi.com/
Responder Con Cita
  #4  
Antiguo 26-03-2016
Avatar de Al González
[Al González] Al González is offline
In .pas since 1991
 
Registrado: may 2003
Posts: 5.604
Poder: 29
Al González Es un diamante en brutoAl González Es un diamante en brutoAl González Es un diamante en brutoAl González Es un diamante en bruto
Le di un tweet desde que lo vi, Jhonny. Gracias por el aporte.

Si tuviera yo que emplear el mismo código, copio aquí cómo lo escribiría (no lo he compilado, aclaro):
Código Delphi [-]
TabControl1.EnumObjects (
  Function (AObj :TFMXObject) :TEnumProcResult
  Begin
    If AObj Is TLabel Then
    Begin
      FMX.Dialogs.ShowMessage ('Encontré la etiqueta, ¡victoria!');
      Result := TEnumProcResult.Stop;
    End
    Else
      Result := TEnumProcResult.Continue;
  End);

Aunque tomando algo de las capacidades de la próxima y prorrogadamente reconstruida GH Freebrary, probablemente escribiría algo así:
Código Delphi [-]
TabControl1.EnumObjects (
  Function (AObj :TFMXObject) :TEnumProcResult
  Begin
    If Result.ghStopWhen (AObj Is TLabel) Then
      FMX.Dialogs.ShowMessage ('Encontré la etiqueta, ¡victoria!');
  End);

Una variante más nativa y estándar, en caso de que yo trabajara en Embarcadero/Idera y me aceptaran añadir estas cosas, podría ser:
Código Delphi [-]
TabControl1.EnumObjects(
  function (AObject: TFMXObject): TEnumProcResult
  begin
    if Result.StopWhen(AObject is TLabel) then
      FMX.Dialogs.ShowMessage('I found the label, bingo!');
  end);

Saludos.

Al González.
Responder Con Cita
  #5  
Antiguo 26-03-2016
Avatar de jhonny
jhonny jhonny is offline
Jhonny Suárez
 
Registrado: may 2003
Ubicación: Colombia
Posts: 7.058
Poder: 29
jhonny Va camino a la famajhonny Va camino a la fama
Gracias por compartirlo Al.

Pinta bastante bien la forma como lo has simplificado

Una pregunta para Al, ¿ghStopWhen es algún método de algún ayudante de TEnumProcResult?, me gustaría (si es posible) ver el código de ghStopWhen, le he hecho click al enlace que tienes en la firma, con el animo de ver su magia pero me sale una página en blanco.
__________________
Lecciones de mi Madre. Tema: modificación del comportamiento, "Pará de actuar como tu padre!"

http://www.purodelphi.com/
http://www.nosolodelphi.com/
Responder Con Cita
  #6  
Antiguo 27-03-2016
Avatar de Al González
[Al González] Al González is offline
In .pas since 1991
 
Registrado: may 2003
Posts: 5.604
Poder: 29
Al González Es un diamante en brutoAl González Es un diamante en brutoAl González Es un diamante en brutoAl González Es un diamante en bruto
Cita:
Empezado por jhonny Ver Mensaje
¿ghStopWhen es algún método de algún ayudante de TEnumProcResult?
La idea es que en efecto lo sea. Es la primera vez que oigo hablar del tipo TEnumProcResult, pero en cuanto tenga que usarlo no dudaré en crearle su extensión, es decir, su ayudante, escribiendo un método como ghStopWhen o algún nombre similar (se aceptan sugerencias de otros posibles identificadores).

En cuanto a la forma de escribir ese método, una manera simple podría ser como en el siguiente código. Uso para este ejemplo el tipo enumerado TEnumControlsResult, el cuál sí está presente en mi versión de Delphi (esto sí lo he probado):
Código Delphi [-]
Type
  TEnumControlsResultHelper = Record Helper For TEnumControlsResult
    Function ghStopWhen (Const ACond :Boolean) :Boolean;
  End;

//...

  Function TEnumControlsResultHelper.ghStopWhen (Const ACond :Boolean) :Boolean;
  Begin
    If ACond Then
      Self := TEnumControlsResult.Stop
    Else
      Self := TEnumControlsResult.Continue;

    Result := ACond;
  End;

Y ya en estas, considerando que los valores ordinales de System.False, System.True, TEnumControlsResult.Continue, TEnumControlsResult.Discard y TEnumControlsResult.Stop son 0, 1, 0, 1 y 2, respectivamente, una implementación más programadoril, que consume menos ciclos de CPU sería:
Código Delphi [-]
  Function TEnumControlsResultHelper.ghStopWhen (Const ACond :Boolean) :Boolean;
  Begin
    Self := TEnumControlsResult (Ord (ACond) * 2);
    Result := ACond;
  End;

Además el método podría ser declarado Inline, aunque en ese caso modificaría un poco su implementación a fin de resolver cierta impericia del compilador (ese tema me gustaría discutirlo en otro hilo):
Código Delphi [-]
  Function TEnumControlsResultHelper.ghStopWhen (Const ACond :Boolean) :Boolean;
  Begin
    Self := TEnumControlsResult (Ord (ACond) * 2);
    Result := Self = TEnumControlsResult.Stop;
  End;

Cita:
Empezado por jhonny Ver Mensaje
[...]le he hecho click al enlace que tienes en la firma, con el animo de ver su magia pero me sale una página en blanco.
Esto es porque suspendí ese enlace hasta que libere la nueva versión de mi biblioteca, la cual fue redefinida por completo. Ahora es 100% orientada a objetos y los únicos elementos globales que declaro son clases e interfaces (incluso a varios ayudantes los declaro en la sección pública de clases de uso general, como TghSys). Ha sido toda una revolución y un crecimiento personal el aplicar mucho de lo nuevo que trae Delphi y erradicando viejos vicios de mi técnica. La GHF de hace tres años me da vergüenza.

Espero ya pronto subir la nueva GH Freebrary a algún repositorio, y tener la satisfacción de ofrecérselas y recibir productiva retroalimentación. Quizá esta vez sí la uses, Jhonny. Intentaré que sea digna de ello.

Última edición por Al González fecha: 27-03-2016 a las 06:21:53.
Responder Con Cita
  #7  
Antiguo 26-03-2016
Avatar de AgustinOrtu
[AgustinOrtu] AgustinOrtu is offline
Miembro Premium
NULL
 
Registrado: ago 2013
Ubicación: Argentina
Posts: 1.858
Poder: 15
AgustinOrtu Es un diamante en brutoAgustinOrtu Es un diamante en brutoAgustinOrtu Es un diamante en brutoAgustinOrtu Es un diamante en bruto
Muy bueno, me recuerda mucho a esta pequeña joya creada por David Heffernan que utilizo para Vcl, y me permite escribir este tipo de codigo, utilizando genericos, predicados y acciones:

Código Delphi [-]

procedure TForm1.btnCountAllClick(Sender: TObject);
begin
  InfoMsgFmt('%d', [TControls.ChildCount< TWinControl >(Self)]);
end;

procedure TForm1.btnCountButtonsClick(Sender: TObject);
begin
  InfoMsgFmt('%d', [TControls.ChildCount< TWinControl >(Self, function(AControl: TWinControl): Boolean
  begin
    Result := AControl is TButton
  end)]);
end;

procedure TForm1.btnWalkControlsClick(Sender: TObject);
begin
  TControls.WalkControls< TWinControl >(Self, procedure(AControl: TWinControl)
  begin
    InfoMsg(AControl.ClassName);
  end);
end;

Saludos

Última edición por AgustinOrtu fecha: 26-03-2016 a las 21:45:17. Razón: Los genericos no salen correctamente :(
Responder Con Cita
  #8  
Antiguo 26-03-2016
Avatar de jhonny
jhonny jhonny is offline
Jhonny Suárez
 
Registrado: may 2003
Ubicación: Colombia
Posts: 7.058
Poder: 29
jhonny Va camino a la famajhonny Va camino a la fama
Cita:
Empezado por AgustinOrtu Ver Mensaje
Muy bueno, me recuerda mucho a esta pequeña joya creada por David Heffernan que utilizo para Vcl, y me permite escribir este tipo de codigo, utilizando genericos, predicados y acciones:
Acabo de echarle un vistazo y estoy de acuerdo con lo que dices, una joya.
__________________
Lecciones de mi Madre. Tema: modificación del comportamiento, "Pará de actuar como tu padre!"

http://www.purodelphi.com/
http://www.nosolodelphi.com/
Responder Con Cita
Respuesta


Herramientas Buscar en Tema
Buscar en Tema:

Búsqueda Avanzada
Desplegado

Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro

Temas Similares
Tema Autor Foro Respuestas Último mensaje
Crear un TPanel dentro de un TPanel dentro de un TScrollBox TiammatMX OOP 6 10-02-2014 16:12:08
Recorrer una tabla dentro de un Procedure en MSSQL Softweb SQL 5 21-07-2010 22:08:44
Duda sobre destrucción de objetos compuestos por otros objetos noob OOP 11 16-02-2009 01:28:33
Crear objetos dentro de otro objeto. Nieto OOP 5 29-11-2007 00:09:12
Recorrer todos los objetos creados de una clase propia mierda OOP 1 25-10-2007 20:52:10


La franja horaria es GMT +2. Ahora son las 00:56:29.


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