Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   OOP (https://www.clubdelphi.com/foros/forumdisplay.php?f=5)
-   -   Eliminar un tabsheet de un Page Control (https://www.clubdelphi.com/foros/showthread.php?t=3975)

apicito 26-09-2003 09:13:22

Eliminar un tabsheet de un Page Control
 
Creo un nuevo tabsheet en un page control y en el creo un formulario poniendole como parent este tabsheet. El formulario lo muestro con Show. Cuando cierro el formulario, como puedo eliminar el tabsheet en el que estaba contenido?

roman 26-09-2003 17:17:00

Usa una variable en el formulario que contiene al PageControl para guardar una referencia a la ficha:

Código:

TForm1 = class
private
  Tab: TTabSheet;
end;

Cuando crees la ficha hazlo así:

Código:

Tab := TabSheet.Create(nil);
Tab.PageControl := PageControl1;

y para eliminar la ficha usas:

Tab.Free

// Saludos

apicito 27-09-2003 09:59:02

mi problema lo tengo por que creo un Form2 al que le asigno como parent ese tabsheet y como lo muestro con show (no como show modal) no sé cuando es eliminado form2 y no sé cuando tengo que hacer:
Cita:

Tab.Free

Ruben_Cu 27-09-2003 15:31:15

Hola apicito, despues de crear tu tabsheet (como te explicó Román) al cerrar el form2 usa el siguiente código:
Código:

procedure TForm2.FormClose(Sender: TObject; var Action: TCloseAction);
begin
        Action := caNone;
        form1.Tab.Free;
end;

Por supuesto como Tab es el contenedor de form2 al liberarse él tambien se destruye la form2.
Saludos

apicito 28-09-2003 10:47:56

La solución que me propone Ruben_Cu cierra la última instancia de Tab que se ha creado, por ello lo he intentado con un array de tabSheets de esta forma.
Código:

FORM1
  private
    Contador : Integer;
  public
    Tab : array of TTabSheet;
procedure TForm1.Button1Click(Sender: TObject);
var Formula2:TForm2;
Begin
  inc(Contador);
  Tab[Contador]:=TTabSheet.Create(nil);
  with Tab[Contador] do
    begin
      PageControl:=PageControl1;
      Name:='Pagina'+trim(inttostr(Contador));
      Caption:=Tab[Contador].Name;
    end;
  Formula2:=TForm2.Create(Self);
  with Formula2 do
    begin
      Parent:=Tab[Contador];
      Caption:='Formulario'+trim(inttostr(Contador));
      Numero:=Contador;
      Show;
    end;
end;
FORM2
  public
    Numero:integer;
procedure TForm2.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  Action:=caNone;
  Form1.Tab[Numero].free;
end;

Pero me da un error de violación de acceso en: Tab[Contador]:=TTabSheet.Create(nil);

Ruben_Cu 28-09-2003 16:33:10

Hola apicito, para evitar el error debes declararle un tamaño al array por ejemplo:
Código:

Tab : array[1..5] of TTabSheet;
De esta manera podrás colocar hasta 6 tabsheet con el form2 contenida, debes controlar el contador para evitar errores.
No entiendo bien porque quieres el mismo form2 repetido en todos los tabsheet:confused: ...tu sabrás.
Puedes eliminar el uso de la función TRIM que en este caso no hace nada.
Saludos y suerte

apicito 29-09-2003 09:38:27

Gracias, funcionó correctamente.
Cita:

No entiendo bien porque quieres el mismo form2 repetido en todos los tabsheet ...tu sabrás.
Es un programa para gestionar expedientes y quiero que el usuarios pueda tener varios expedientes abriertos al mismo tiempo.
Un saludo.

__cadetill 29-09-2003 10:01:04

Cita:

Posteado originalmente por Ruben_Cu
De esta manera podrás colocar hasta 6 tabsheet con el form2 contenida
Bueno, yo diría más bien 5 ;)

Otra manera sería utilizar arrays dinámicos y inicializarlos con SetLength (la ayuda sobre los arrays dinámicos que trae una buena explicación).

apicito 29-09-2003 12:51:53

Alguien puede decirme porque si, en vez de utilizar el array de tabs ya creados, utilizo el sistema de crear los tabs cuando abro el form2 con el metodo:
Código:

procedure TForm1.Boton1Click;
var Form2:TForm2;
    PaxNum:Integer;
Begin
  with TTabSheet.Create(self) do
    begin
      PageControl:=PageControl1;
      Name:='Pagina'+trim(inttostr(Contador));
      Caption:='Sesiones';
      PaxNum:=PageIndex;
    end;
  inc(Contador);
  Form2:=TForm2.Create(Self);
  with Form2 do
    begin
      Parent:=PageControl1.Pages[PaxNum];
      Show;
    end;
end;

me da error de desbordamiento de pila y sin embargo:
Código:

procedure Form1.Boton1Click;
var Form2:TForm2;
    PaxNum:Integer;
    Pax:TtabSheet;
Begin
  with TTabSheet.Create(self) do
    begin
      PageControl:=PageControl1;
      Name:='Pagina'+trim(inttostr(Contador));
      Caption:='Sesiones';
      PaxNum:=PageIndex;
      Pax:=PageControl1.Pages[PaxNum];
    end;
  inc(Contador);
  Form2:=TForm2.Create(Self);
  with Form2 do
    begin
      Parent:=Pax;
      Show;
    end;
end;

funciona correctamente?

Ruben_Cu 30-09-2003 02:13:50

Cita:

Posteado originalmente por cadetill
Bueno, yo diría más bien 5 ;)
Estimado amigo, prueba colocar las lineas del programa incluyendo el array y verás que logras 6 tabsheet con la form como hija, ya la séptima form no reconoce al parent, curioso eh??;) Cuando comencé a redactar el mensaje escribí 5 pero al probarlo se comportó con 6 de ahí el número.
Saludos

roman 30-09-2003 06:41:03

Cita:

Posteado originalmente por Ruben_Cu
...prueba colocar las lineas del programa incluyendo el array y verás que logras 6 tabsheet con la form como hija, ya la séptima form no reconoce al parent, curioso eh??;) Cuando comencé a redactar el mensaje escribí 5 pero al probarlo se comportó con 6 de ahí el número.

Puede ser, pero es cuestión de suerte. En el momento más inesperado e inoportuno saldrá a relucir el error con un estimulante "Access Violation" ;)

// Saludos

__cadetill 30-09-2003 10:08:11

Cita:

Posteado originalmente por roman
En el momento más inesperado e inoportuno saldrá a relucir el error con un estimulante "Access Violation" ;)
Tanto como "estimulante", no se no se, a mi estos errores son los que más quebraderos de cabeza me dan :D :mad:

Respecto a las lineas de código que envía el amigo apicito, pues la verdad no entiendo porque un código funciona y el otro no :confused:

Ruben_Cu 01-10-2003 01:58:10

Cita:

Posteado originalmente por roman
Puede ser, pero es cuestión de suerte. En el momento más inesperado e inoportuno saldrá a relucir el error con un estimulante "Access Violation" ;)
Si ya lo decía en mi post que pensé que eran 5 pero probé varias veces y siempre colocó seís después del post de cadetill volví a rehacer el programa y continuó dando seís sin el estimulante error, y si algo he aprendido es que esto o funciona o no funciona. Explicación no tengo, no se uds.
Saludos

roman 01-10-2003 02:51:49

Cita:

Posteado originalmente por Ruben_Cu
Si ya lo decía en mi post que pensé que eran 5 pero probé varias veces y siempre colocó seís después del post de cadetill volví a rehacer el programa y continuó dando seís sin el estimulante error, y si algo he aprendido es que esto o funciona o no funciona. Explicación no tengo, no se uds.
Saludos

Yo creo que la lección no es "esto funciona o no funciona", sino "esto no está bien aunque en ocasiones no de problemas"

Haciendo unas pruebas me dió lo siguiente:
  • Si el arreglo se declara como variable de la unidad no se genera ningún error
  • Si el arreglo se declara como campo del formulario no se genera error al ejecutarse pero al cerrar la aplicación se generan de esos mensjaes "Runtime Error" que se despliegan cuando ya se ha cerrado el mecanismo de excepciones.
  • Si el arreglo se declara como variable local a un procedimiento se genera un "Access violation"

Y, desde luego, si habilitamos la opción "Range check error" del compilador entonces se genera un error durante la ejecución antes de acceder a parte prohibidas de la memoria.

El punto aquí es (en mi opinión):


Evítense prácticas incorrectas de programación aún cuando no parezca haber errores.


// Saludos

Ruben_Cu 01-10-2003 03:12:27

Cita:

Posteado originalmente por roman
Yo creo que la lección no es "esto funciona o no funciona", sino "esto no está bien aunque en ocasiones no de problemas"
¿Como es posible que en ocasiones el compilador lo ve bien y en otras no?
Cita:

Posteado originalmente por roman

Si el arreglo se declara como variable de la unidad no se genera ningún error


Entonces estamos ante la ruptura de un paradigma o simplemente ante un 'X files' :confused:

roman 01-10-2003 05:46:18

Cita:

Posteado originalmente por Ruben_Cu
¿Como es posible que en ocasiones el compilador lo ve bien y en otras no?

Supongo que depende del segmento de memoria en donde se coloque la variable.

Voy a especular porque yo de esto no sé nada:

[especular]
Dependiendo de donde se declare la variable ésta se colocará en distintos segmentos de memoria. Algunas se colocan en el segmento de código (CODE segment) de manera que al escribir en una dirección que no nos corresponde se genera el "Access Violation" al intentar escribir sobre la parte de memoria donde se pone el código cuando el programa se carga en memoria.

En otras ocasiones se colocara en un segmento especial para datos (DATA segment) y, si no hay nada contiguo y se trata de un área que el manejador de memoria de Delphi ya reservó pues no pasará nada grave.
[/especular]

Aquí te pongo una prueba rápida que hice:

Inmediatamente después de la declaración del formulario declara lo siguiente:

Código:

var
  Form1: TForm1;
  Fichas: array[1..5] of Integer;
  Prueba: Integer;

En algún lugar ejecuta la instrucción:

Código:

I := 6;
Fichas[i] := 84;
Caption := IntToStr(Prueba);

¿Qué crees que apareció en la barra de título del formulario?

84

Suena lógico ¿no?

Ficha[6] accedió a la parte de la memoria inmediatamente después del arreglo Fichas. Y ahí estaba la variable Prueba.

No causa error pues es sólo el valor de una variable que se afecta pero desde luego ¡está mal!

No es que el compilador a veces marque errores y a veces no. Es que depende de muchas circunstancias, de qué código tengamos.

El ejemplo anterior muestra que no veremos ningún error pero cuando nuestro programa muestre cosas raras por la alteración del valor de la variable Prueba, pasaremos ratos difícilies (¿estimulantes?) intentando encontrar la falla.

Por eso, repito, debemos ajustarnos a la programación correcta pues no tiene caso intentar averiguar de qué manera está funcionando el compilador.

// Saludos


La franja horaria es GMT +2. Ahora son las 02:14:28.

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