PDA

Ver la Versión Completa : tRABAJO CON CONTROLES CREADOS EN EJECUCION


bustio
07-02-2005, 20:04:27
Hola!

Mi duda de hoy es esta:

Tengo un boton donde creo una cantidad de Edits que me dice un SpinEdit... eso lo hago en un momento determinado. A estos edits les doy el nombre de EDIT + i, donde i es la variable del ciclo de control que uso para crear los controles. Estos Edits luego contandran valores... y estos valores en otro momento posterior necesito tomarlos dentro de una variable.... Pero necesito tanto los valores de todos los edits que creo como los de algunos... Y no se como acceder al edit especifico para tomar su valor.. o a todos.
Como puedo hacer para dentro de un ciclo recorrer uno a uno los edits y tomarles su valor??

GRACIAS....

Lazaro Bustio Martinez.

Coco
07-02-2005, 20:21:24
Cada uno de los componentes siempre estan dentro de otro (Parent) el cual es el contenedor. Este contenedor tiene una coleccion de todos los componentes que tiene, tendrias que recorrer la coleccion, detectar cual es edit y aplicarle la funcion que tu deseas. Por ej:

function ComponentNamed( Container: TComponent;
ComponentName: TComponentName): TComponent;
var i: integer;
begin
Result:= nil;
for i:= 1 to Container.ComponentCount do
begin
if upperCase(container.Components[i-1].Name) = upperCase (ComponentName)
then begin
Result:=container.Components[i-1];
break;
end;
end;
end;

Esta funcion busca un componente por su nombre y te lo devuelve.
Saludos

SyncMaster
08-02-2005, 02:44:29
Yo en lo personal utilizo otro metodo. Si tengo por ejemplo 20 EDIT dentro de una form a todos ellos les pongo numeros consecutivos de esta forma :

Edit1
Edit2
Edit3
.
.
.
Edit20

Cuando necesito recorrerlos para saber sus valores o para realizar cualquier otra operación lo hago de la siguiente forma :

For i:=1 To 20 Do
With TEdit (FindComponent ('Edit'+IntToStr(i)) Do
Begin
// Aqui hago lo que tenga que hacer con su valor
End;

¿Sirve?

Una forma similar con los botones, Le asignos diferentes numero en la propiedad TAG del boton para diferenciarlos, pero le asigno el mismo evento CLIC a todos y dentro del procedimiento del evento clic utilizo la clausula CASE para identificar donde hizo clic el user

Case (Sender as TComponent).Tag of
1 : ; //
2 : ; //
.
.
End;

Saludos

bustio
08-02-2005, 17:19:11
¿Sirve?


POr supuesto que sirve!!! Y bien que lo hace!! Muchas gracias!

Pero mis pesares no terminan ahi.. resulta que ahora necesito yo hacer mas o menos lo mismo pero con RadioButtons.. o sea, la idea es la siguiente:
Yo quiero mostrar una cantidad de Edits, y junto a ellos poner RadioButtons.. uno por cada Edit y que el usuario pueda darle valores a los EDITS y marque en el RADIOBUTTON el que es el correcto. Es para generar un sistema de Cuestionarios. Cuando el usuario presione el Boton ACEPTAR, debo recorrer todos los Edits y tomar sus valores para almacenarlos en una BD, y tambien debe recorrer los RadioButtons para ver cual es el que esta seleccionado y de acuerdo al valor que tenga el RadioButton se le inserta a la tupla en cuestion un valor 0 o 1(La pregunta es lo que esta en el EDIT y si es Verdadero o Falso es lo que dice el RadioButton). Pero cuando intento tomar los valores del RadioButton como tu recorres los Edite me da una excepcion:

Project TM2.exe raised exception class EAccessViolation with message 'Access violation at address 005F4CB2 in module 'TM2.exe'. Read of address 00000000'. Process stopped. Use Step or Run to continue.

Tal vez sea en la manera en que creo los componentes en tiempo de ejecucion:



procedure TFrmCrearPreguntas.Button1Click(Sender: TObject);
var
i : Integer;
TipoPregunta : String;
begin
TipoPregunta := dblucbTipoPreguntas.Text;
for i := 1 to CantElementos do
begin
Edit := TEdit.Create(Self);
Edit.Name := 'Edit' + IntToStr(i);
Edit.Parent := Panel3;
Edit.Text := '';
Edit.Width := 220;

RadioButton := TRadioButton.Create(Self);
RadioButton.Name := 'RadioButton'+ IntToStr(i);
RadioButton.Parent := Panel3;
//RadioButton.Checked := false;
RadioButton.Caption := '';
RadioButton.Width := 20;

If ((i mod 2) = 0) then
begin
Edit.Left := 290;
Edit.Top := 5 + (i * 13) - 13;

RadioButton.Left := 520;
RadioButton.Top := 5 + (i * 13) - 13;
end
else
begin
Edit.Left := 20;
Edit.Top := 5 + (i * 13);

RadioButton.Left := 250;
RadioButton.Top := 5 + (i * 13);
end;
end;
end;



O la manera en que trato de acceder a la propiedad Checked del RadioButton...:

if TRadioButton(FindComponent('RadioButton'+IntToStr(i))).Checked then
showmessage('true'); // el showmessage es para ir probando...


Y no se que mas inventar para que esto sirva.

roman
08-02-2005, 17:52:23
Si vas a crear controles por código y requieres acceder a ellos sistemáticamente, no tiene caso abusar de técnicas que sirven para cuando uno no tiene control sobre la creación de los componentes. Código como


for I := 0 to 20 do
FindComponent('Edit' + IntToStr(I))


puede verse muy claro pero es muy ineficiente. FindComponent lo que hace es recorrer todos los componentes hasta encontrar uno con el nombre dado. El resultado: una innecesaria doble iteración de todos los componentes.

Mejor crea las estructuras de datos que necesites para el efecto. Por ejemplo:


type
TTupla = record
Edit: TEdit;
RadioButton: TRadioButton;
end;

var
Tuplas: array of TTupla;


De esta forma almacenas los controles creados en el arreglo dinámico Tuplas y cuando requieras recorrerlos simplemente harás:


for I := Low(Tuplas) to High(Tuplas) do
begin
{
Haces lo que requieras con
Tuplas[I].Edit y Tuplas[I].RadioButton
}
end;


EDITO:

Aclaro un poco: Los controles los creas igual que hasta ahora pero a su vez creas una tupla por cada uno y asignas los controles creados a los elementos de la tupla o incluso directamente:


// Asignas el número de controles que requieras
SetLength(Tuplas, 20);

Tuplas[0].Edit := TEdit.Create(...);
Tuplas[0].RadioButton := TRadioButton.Create(...);

....


Como verás, de esta forma no requieres asignar ningún nombre a los Edits y RadioButtons.

// Saludos