PDA

Ver la Versión Completa : Vaciar un Timage


Masu
11-12-2003, 22:29:53
Hola a tod2@s,

tengo un ligero problema, que quizas sea un tonteria (seguro) pero no doy con la solucion.

Tengo un Timage, y cargo una imagen al mismo, sin problemas, los estrecho y se ajusta perfecto. Pero ahora viene mi problema, ¿como borro del Timage, la imagen que he cargao y lo dejo vacio, como si no hubiese cargao antes otra imagen?

Gracias

roman
11-12-2003, 22:36:46
Durante el diseño: Abres el cuadro de edición de la propiedad Picture y oprimes el botón "Clear"

Durante la ejecución: Image1.Picture := nil;

// Saludos

Masu
11-12-2003, 22:41:35
Que velocidad, muchisimas gracias.

Amilius
02-02-2004, 03:32:53
Durante el diseño: Abres el cuadro de edición de la propiedad Picture y oprimes el botón "Clear"

Durante la ejecución: Image1.Picture := nil;

// Saludos

¿Seguro que el objeto referenciado por "Picture" es destruido al terminar el programa?

Tal vez sea mejor:

Image1.Picture.Free;
Image1.Picture := nil;

o abreviado

Image1.Picture.FreeNil;

Ojo que si existe otra referencia al mismo objeto, que podría ser usada después, es necesario colocarla en "nil" antes de destruir el objeto u ocurrirá un error ya que esa otra referencia seguirá apuntando a la posición donde estaba el objeto referenciado por Picture.

Saludos.

jachguate
02-02-2004, 05:31:12
No te olvides que Picture es una propiedad de la clase TImage. Si te das el tiempo de revisar el código de la VCL te darás cuenta que en el método de asignación de la propiedad (SetPicture) cuando se recibe una referencia a nil, la memoria reservada por la imagen actual en efecto se libera.

Trataré de explicarte la forma en que trabaja la VCL en este sentido.

Las propiedades (un excelente invento de borland, creo yo) son una forma fantástica de introducir efectos secundarios de este tipo que al final ahorran trabajo y líneas de código. Cuando vos haces una asignación, en realidad ocurre tras bambalinas una serie de acciones que logran que esa acción sea efectiva. Por ejemplo, cuando asignas un valor al Caption de un TLabel, no solo se cambia el valor de este, sino se inválida el área que ocupa en pantalla, de manera que si está visible, el cambio se vea reflejado al usuario. Si no fuera así, siempre tendrias que llamar a Invalidate después de hacer un cambio para que este se reflejara.

En ocasiones, estas propiedades son objetos, y es muy importante comprender los efectos de invocar directamente los métodos de estos objetos, sobre todo los constructores y destructores, pues es muy probable que provoquemos un fallo en nuestro programa (como podras comprobar si compilas la recomendación que das, seguramente provocará un AccessViolation). De hecho, nunca he visto una propiedad de un objeto de la VCL que requiera que su constructor/destructor sea invocado directamente, con componentes de terceros... mejor revisar la documentación, y el código si está disponible.

Algo similar ocurre con la asignación de valores a estas propiedades, por ejemplo cuando querés asignar una imágen contenida en una variable (digamos una instancia de TBitmap) a un TImage, basta con hacer Image1.Picture := MyBMP; Si la VCL no estubiera preparada para manejar esto, en realidad harias que la propiedad Picture apunte a la misma dirección donde apunta MyBMP, y al liberar este, dejarías al TImage apuntando a una dirección donde en realidad ya no existe un objeto, lo cual a la postre seguramente provocaría un AccessViolation. Nuevamente si te das una vuelta por las unidades de la VCL verás que en realidad se hace una copia de la imágen (mediante assign), manteniendo de esa forma por un lado la independencia de las propiedades de la VCL con respecto de tus propias variables locales (o globales), y por el otro la responsabilidad de cada uno de liberar la memoria y/o recursos consumidos, la VCL su propia memoria, y vos la de tus variables, (llamando a MyBMP.Free cuando ya no lo necesites mas).

Espero haber sido claro y no confundirte con todo este rollo...

Hasta luego.

;)

Amilius
12-02-2004, 19:23:20
Sip, tienes razón, tome a "picture" textualmente como referencia a objeto y no como propiedad. Y si se llamaría a "free" directamente, el componente no tendría forma de "enterarse" de que el objeto que apunta su referencia interna ya fue destruido y efectivamente ocasionaría un error.

danielnakata
01-06-2010, 20:59:35
He estado leyendo el foro, el cual me saco de unas dudas que tenia, lo cual les agradezco mucho. Les dejo un fragmento de codigo que elabore, se trata de cargar un TImage con un openDialog, filtrando obviamente solo las imagenes y obteniendo despues el tamaño de la imagen seleccionada, si el tamaño sobrepasa 500kb (aprox) manda un mensaje de error, limpia el TImage y cierra los archivos (que se abren para obtener el tamaño de la imagen).

Espero este aporte sirva para alguien
Saludos!!!



//codigo del boton donde ejecuto el openDialog para buscar la imagen

procedure TfrmSubir_imagenes.btnArchivoClick(Sender: TObject);
var narch:String; tam: LongWord; arch2: Thandle; arch: file;
begin
try
if(open1.Execute)then //ejecuta el open dialog
begin
narch := open1.FileName; //obtiene el nombre de la imagen
txtArchivo.Text := narch; //carga un TEdit con el nombre del archivo
//reset(arch);
imagen1.Picture.LoadFromFile(narch); //carga el Timage con la imagen seleccionada


AssignFile(arch, narch); //crea un archivo con el nombre de la imagen
reset(arch);//reinicializa el archivo recien creado para su manejo

if(FileSize(arch) > 3799)then //valida el tamaño que sea menor de 500kb (aprox)
begin
MessageDlg('La imagen es demasiado grande, debe ser menor a 450kb y en '+#13+#10+'formato jpg'+#13+#10+'Seleccione otra imagen o edite la imagen deseada', mtError, [mbOK], 0); //mensaje de error
//imagen1.Picture.Free;
imagen1.Picture := nil; //LIMPIA EL TImage
self.Repaint; //refresca la forma
txtArchivo.Clear; //limpia el campo de texto
CloseFile(arch); //cierra el archivo (necesario para que no mande errores al querer abrir otra vez el mismo archivo
exit; //sale del procedimiento
end;

CloseFile(arch); //cierra el archivo
imagen1.Hint := narch; //asigna al hint del TImage la ruta de la imagen cargada
self.Repaint; //refresca la forma
end
else
begin
MessageDlg('Debe seleccionar un archivo para subir', mterror, [mbOk], 0);
end;
except
on e:Exception do
begin
MessageDlg('Error al buscar el archivo de la imagen debido a:'+#10+e.Message, mtError, [mbOk], 0);
exit;
end;
end;
end;