Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   OOP (https://www.clubdelphi.com/foros/forumdisplay.php?f=5)
-   -   Error Abstract Error y Access violation (https://www.clubdelphi.com/foros/showthread.php?t=30459)

zvf 06-04-2006 18:15:11

Error Abstract Error y Access violation
 
Hola!

Yo ya les habia escrito antes para platicarles sobre estos dos errores que me ocurrian, y estuvieron revisando parte de mi codigo, hice todos los movimientos que me indicaron y no los he podido resolver.

Yo he continuado programando el resto del sistema, ignorando esos errores, pero de todas formas, lo reviso y no se como quitarselos, no veo el problema en mi codigo.

Y lo que pasa es que realiza absolutamente todas las lineas de codigo de manera correcta, y antes del end; manda el error. Y es variable, algunas veces manda el error Abstract y otras el Access violation, por eso no puedo ubicar en donde pasa, porque lo manda una linea antes de que termine la ejecucion.

Como me urge entregar el sistema la proxima semana, quiero ver la forma de ocultar esos errores, para poderlo entregar y con mas calma despues revisar el codigo, aunque nose como porque ya lo he revisado.

Pero lo he puesto con excepciones y no cacha esos errores.

¿Saben como puedo hacerle? :confused: :confused:

Si saben como ocultarlos me ayudaria mucho, porque en verdad el programa funciona muy bien, no se interrumpe con esos errores ni causa problemas.

MUCHAS GRACIAS!!

samantha jones 07-04-2006 01:05:17

A mi me ocurria cuando estaba usando un metodo virtual en una clase heredada y aun no lo habia definido. Espero y te ayude.

Saludos

zvf 07-04-2006 01:07:11

Gracias. Pero yo no uso metodos virtuales, ni clases heredadas, todo esta en una misma unit.

reina 07-04-2006 02:50:51

Holaaa mira no vi tu hilo donde comentas tus errores, pero lo que si te puedo ecir es que tu programa bien no debe funcionar ya que un acces violation es un acceso invalido a memoria..
Te escribo una lista de excepciones a ver si te sirven, estas las podrias cachar ahi!:D :
Exception Base class

EAbort Abort without dialog
EAbstractError Abstract method error
AssertionFailed Assert call failed
EBitsError Boolean array error
ECommonCalendarError Calendar calc error
EDateTimeError DateTime calc error
EMonthCalError Month calc error
EConversionError Raised by Convert
EConvertError Object convert error
EDatabaseError Database error
EExternal Hardware/Windows error
EAccessViolation Access violation
EControlC User abort occured
EExternalException Other Internal error
EIntError Integer calc error
EDivByZero Integer Divide by zero
EIntOverflow Integer overflow
ERangeError Out of value range
EMathError Floating point error
EInvalidArgument Bad argument value
EInvalidOp Inappropriate operation
EOverflow Value too large
EUnderflow Value too small
EZeroDivide Floating Divide by zero
EStackOverflow Severe Delphi problem
EHeapException Dynamic memory problem
EInvalidPointer Bad memory pointer
EOutOfMemory Cannot allocate memory
EInOutError IO error
EInvalidCast Object casting error
EInvalidOperation Bad component op
EMenuError Menu item error
EOSError Operating system error
EParserError Parsing error
EPrinter Printer error
EPropertyError Class property error#
EPropReadOnly Invalid property access
EPropWriteOnly Invalid property access
EThread Thread error
EVariantError Variant problem

Esto lo podes encontrar en la ayuda de delphi, si veo tu codigo tal veZ te pueda ayudar..espero lo soluciones.

exitos

LA PATRIA SERA LIBRE!

zurech 07-04-2006 10:28:48

Si estos errores te ocurren al terminar la aplicacion, prueba a finalizarla de la siguiente manera (es como lo hago yo por un problema similar):

Código Delphi [-]
{
Esta funcion, como su bonito nombre indica sirve para obtener solo el nombre del EXE, en lugar de la ruta completa
}
function TFrmPrincipal.soloExe(archivo : String) : String;
var
  resultado : String;
  i : integer;
begin
  for i:=1 to Length(archivo) do
    begin
      if (archivo[i] = '\') then
        resultado := ''
      else resultado := resultado + archivo[i];
    end;

  result := resultado;
end;

{
Funcion que mata el proceso de la aplicacion, y sus procesitos (hijos)
}
function TFrmPrincipal.KillTask(FileName:String):integer;
 var
     ContinueLoop:BOOL;
     FSnapshotHandle:THandle;
     FProcessEntry32:TProcessEntry32;
 const
     PROCESS_TERMINATE=$0001;
 begin
     FSnapshotHandle:=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
     FProcessEntry32.dwSize:=Sizeof(FProcessEntry32);
     ContinueLoop:=Process32First(FSnapshotHandle,FProcessEntry32);
     while integer(ContinueLoop)<>0 do
     begin
         if
 ((UpperCase(ExtractFileName(FProcessEntry32.szExeFile))=UpperCase(FileName))
             or (UpperCase(FProcessEntry32.szExeFile)=UpperCase(FileName)))
 then

 Result:=Integer(TerminateProcess(OpenProcess(PROCESS_TERMINATE,BOOL(0),

                                     FProcessEntry32.th32ProcessID),0));
           ContinueLoop:=Process32Next(FSnapshotHandle,FProcessEntry32);
     end;
     CloseHandle(FSnapshotHandle);
end;

procedure TFrmPrincipal.Terminar();
begin
  try
    KillTask (soloExe(Application.ExeName));
  except on exception do end;
end;

Lepe 07-04-2006 12:22:59

NO, NO Y NO.

El problema es grave, como indica un abstract error y un access violation, y el problema no es de código sino de concepto, para eso tendrás que estudiarlo.

Las clases bases de un form usan abstract; virtual etc en sus métodos, por tanto si te dan esos errores es que estas lanzando las ventanas mal. Normalmente es porque no identificas el Parent/Owner de una ventana o que le das información incongruente, mira este código:

Código Delphi [-]
Form1 := Tform1.Create(application);
....

Form1.Free;

El error está en decirle que el objeto Application es el encargado de destruir la ventana, pero despues te encargas tú por código de liberarla. Cuando termine tu programa el objeto Application intentará destruir el Form1, pero como ya está destruido.... Access violation.

De la misma forma al cerrar esa ventana una y otra vez te dará un error de Abstract Error, (es lo más probable).

Tienes que tener claro que el Parent de una ventana, por ejemplo, es solo para saber dentro de qué control se va a mostrar.

El Owner (dueño) de un control/ventana es el que se encarga de destruirlo, y puede ser distinto al Parent (Padre).

A ese código se suma otro error más. Cuando se hace el Form1.Free, la memoria se libera, pero la variable Form1 se queda apuntando a la zona de memoria donde estaba, por tanto, si vuelves a llamar a Form1.Free en compilación no da fallos, pero en Ejecución dará un Access Violation.

Formas correctas:
Código Delphi [-]
try
  Form1 := Tform1.Create(nil);
...
finally
  FreeandNil(Form1);
end;
Se crea, pero nadie lo destruirá.... porque lo destruyo por código yo.


Código Delphi [-]

  Form1 := Tform1.Create(Application);
...
El objeto se destruye cuando termina la aplicación, es decir, desde que se crea, hasta que finalice la applicación, el Form1 estará en Memoria.

Hay otras formas, por ejemplo con ventanas modales, pero todo se resume a lo mismo: Indicar bien los Owner y tener controlado (conceptualmente) cuando y donde se destruyen las ventanas.



Saludos

zurech 07-04-2006 12:37:29

Lepe muchas gracias tio, son estos pequeños conceptos que no se tienen del todo claros lo que diferencia el buen codigo del mal codigo.

zvf 07-04-2006 17:27:18

Gracias a todos!
Vean, creo que por ahi va el asunto, porque yo creo un boton en tiempo de ejecucion, mi codigo es el siguiente:

Código Delphi [-]
Procedure TFPrincipal.CreaBoton;
  var NewBoton : TLabel;
      nombre : string;
      scontador:string;
      sventana_actual : string;
   begin
       if (band = 0) then  //PRIMER BOTON QUE CREA
               begin
               ventana_actual:=1;
               sventana_actual:= IntToStr (ventana_actual);
               margen_izq := margen_izq_ini;
               margen_sup := margen_sup_ini;
               band := 1;
               end
        else
               begin
                margen_izq := margen_izq_ant;
                margen_sup := margen_sup_ant + alto_boton + margen_sup_ini;
                if (margen_sup > margen_inf) then
                    begin
                     margen_izq := margen_izq + margen_izq_ini;
                     margen_izq := margen_izq + ancho_boton;
                     margen_sup := margen_sup_ini;
                    end;
                if (margen_izq > margen_dere) then
                    begin
                     margen_izq := margen_izq_ini;
                     margen_sup := margen_sup_ini;
                     ventana_actual := ventana_actual+1;
                     sventana_actual:= IntToStr (ventana_actual);
                    end;
               end;
     with NewBoton do
        begin
        case ventana_actual of
          1: begin
             NewBoton := TLabel.create(FPrincipal.GroupBoxProd1);
             Parent := FPrincipal.GroupBoxProd1;
             end;
          2: begin
             NewBoton := TLabel.create(FPrincipal.GroupBoxProd2);
             Parent := FPrincipal.GroupBoxProd2;
             end;
          3: begin
             NewBoton := TLabel.create(FPrincipal.GroupBoxProd3);
             Parent := FPrincipal.GroupBoxProd3;
             end;
          4: begin
             NewBoton := TLabel.create(FPrincipal.GroupBoxProd4);
             Parent := FPrincipal.GroupBoxProd4;
             end;
          end;
        scontador:= IntToStr (contador);
        nombre:= 'Boton';
        Name := nombre+scontador;
        Color:= clMoneyGreen;
        Width := ancho_boton;
        Height := alto_boton;
        Left := margen_izq;
        Autosize := false;
        Top := margen_sup;
        Caption := varCaption;
        if soyingrediente <>1 then
             OnClick := mostrar_productos
        else
             OnClick := mostrar_productos;
        margen_izq_ant := margen_izq;
        margen_sup_ant := margen_sup;
      end; //fin del con hacer
  end;
//////  FIN DEL PROCEDIMIENTO CREAR UN BOTON EN TIEMPO DE EJECUCION   /////////

zvf 07-04-2006 17:28:03

Y con este código lo mando destruir:

Código Delphi [-]
///////////PROCEDIMIENTO DESTRUIR BOTONES ///////////////////////////////
procedure TFPrincipal.DestruirBotones;
  var i, botonesCreados:integer;
begin
  botonesCreados:=FPrincipal.GroupBoxProd1.ControlCount;
 for i:=botonesCreados-1 downto 0 do
       begin
       FPrincipal.GroupBoxProd1.Controls[i].Free;
       end;
 botonesCreados:=FPrincipal.GroupBoxProd2.ControlCount;
 for i:=botonesCreados-1 downto 0 do
       begin
       FPrincipal.GroupBoxProd2.Controls[i].Free;
       end;
 botonesCreados:=FPrincipal.GroupBoxProd3.ControlCount;
 for i:=botonesCreados-1 downto 0 do
       begin
       FPrincipal.GroupBoxProd3.Controls[i].Free;
       end;
 botonesCreados:=FPrincipal.GroupBoxProd4.ControlCount;
 for i:=botonesCreados-1 downto 0 do
       begin
       FPrincipal.GroupBoxProd4.Controls[i].Free;
       end;
 inicializa;
end;

zvf 07-04-2006 17:28:44

Aqui, como puedo usar la excepcion que me pusiste como ejemplo?

Gracias, de verdad , mucha gracias por su ayuda!

Lepe 07-04-2006 18:30:36

Veo un detalle:
Código Delphi [-]
 with NewBoton do
        begin
        case ventana_actual of
          1: begin
             NewBoton := TLabel.create(FPrincipal.GroupBoxProd1);
             Parent := FPrincipal.GroupBoxProd1;
....
   scontador:= IntToStr (contador);
        nombre:= 'Boton';
        Name := nombre+scontador;
   end; // del with

No veo lógico que uses el With NewBoton do y acto seguido modifiques el valor porque creas un Tlabel nuevo.

Sugiero que muevas la frase With NewBoton do más abajo:
Código Delphi [-]
        case ventana_actual of
          1: begin
             NewBoton := TLabel.create(FPrincipal.GroupBoxProd1);
             Parent := FPrincipal.GroupBoxProd1;
             end;
          2: begin
             NewBoton := TLabel.create(FPrincipal.GroupBoxProd2);
             Parent := FPrincipal.GroupBoxProd2;
             end;
          3: begin
             NewBoton := TLabel.create(FPrincipal.GroupBoxProd3);
             Parent := FPrincipal.GroupBoxProd3;
             end;
          4: begin
             NewBoton := TLabel.create(FPrincipal.GroupBoxProd4);
             Parent := FPrincipal.GroupBoxProd4;
             end;
          end;
    with NewBoton do
        begin
        scontador:= IntToStr (contador);
        nombre:= 'Boton';
        Name := nombre+scontador;
        Color:= clMoneyGreen;
        Width := ancho_boton;
        Height := alto_boton;
        Left := margen_izq;
        Autosize := false;
        Top := margen_sup;
        Caption := varCaption;

  // esto lo has estado modificando... seguro, porque no tiene mucha logica ;)
        if soyingrediente <>1 then
             OnClick := mostrar_productos
        else
             OnClick := mostrar_productos;

        margen_izq_ant := margen_izq;
        margen_sup_ant := margen_sup;
      end; //fin del con hacer

Por otra parte, cuando creas los labels, le dices que tiene un dueño, y realmente lo vas a destruir tú, pasale un "nil" mejor.

Saludos.

zvf 07-04-2006 21:12:13

Lo puse de esta forma :

Código Delphi [-]
case ventana_actual of
          1: begin
             NewBoton := TLabel.create(nil);
             Parent := FPrincipal.GroupBoxProd1;
             end;
          2: begin
             NewBoton := TLabel.create(nil);
             Parent := FPrincipal.GroupBoxProd2;
             end;
          3: begin
             NewBoton := TLabel.create(nil);
             Parent := FPrincipal.GroupBoxProd3;
             end;
          4: begin
             NewBoton := TLabel.create(nil);
             Parent := FPrincipal.GroupBoxProd4;
             end;
          end;
        with NewBoton do
        begin
        scontador:= IntToStr (contador);
        nombre:= 'Boton';
        Name := nombre+scontador;
        Color:= clMoneyGreen;
        Width := ancho_boton;
        Height := alto_boton;
        Left := margen_izq;
        Autosize := false;
        Top := margen_sup;
        Caption := varCaption;
        if soyingrediente <>1 then
             OnClick := mostrar_productos
        else
             OnClick := mostrar_productos;
        margen_izq_ant := margen_izq;
        margen_sup_ant := margen_sup;
      end; //fin del con hacer

Y al correr el ejecutable, manda una mensaje de error:
:confused: :confused: :confused: stack overflow :confused: :confused: :confused:

Y desaparece ese mensaje enseguida y no se abre el programa.
¿Sabes porque es esto?

zvf 07-04-2006 23:39:02

ya vi, eso pasa cuando intento cambiar el with new boton, como tu me digiste de lugar.

Ahorita ya les puse nil a los TLabel en la creacion, el with new boton lo deje igual como lo tenia, no lo pude cambiar como tu me sugeriste.

Pero sigue el error :confused: :confused: :confused:

Lepe 07-04-2006 23:54:47

Pues claro, fallo mio, perdona.

Código Delphi [-]
      case ventana_actual of
          1: begin
             NewBoton := TLabel.create(FPrincipal.GroupBoxProd1);
             Parent := FPrincipal.GroupBoxProd1;<<<<< aqui el error
             end;

Al cambiar el with NewBoton do, la linea marcada la interpreta de forma distinta, Ahora está intentando cambiar el padre a ¡¡ la ventana !!.

Al pasarlo abajo, hay que poner
Código Delphi [-]
    NewBoton.Parent := FPrincipal.GroupBoxProd1;
para todas las opciones del "case".

Para futuras veces Stack Overflow es que la pila de llamadas se ha desbordado, esto suele ocurrir en funciones que se llaman a sí mismas en un bucle infinito, o bien que se pase del límite establecido para la pila.

La verdad es que me desconcertó por unos segundos el tipo de error que daba ;).

Saludos

zvf 08-04-2006 00:03:31

Fijate que ya lo cambie, pero el error sigue :confused: :confused:

Lo deje asi:

Código Delphi [-]
          1: begin
             NewBoton := TLabel.create(nil);
             NewBoton.Parent := FPrincipal.GroupBoxProd1;
             end;

Pero los errores siguen apareciendo, y no veo donde este mi error. ¿No hay forma de ocultarlos? :(

roman 08-04-2006 01:14:31

Quiero hacer una aclaración en cuanto a los owners.

Ciertamente, el Owner de un Component es quien se encargará de destruirlo, pero no significa que sea su prerogativa exclusiva. Un Component, aun con dueño puede ser destruido explícitamente sin mayores problemas.

El destructor de TComponent hace esto:

Código Delphi [-]
if Owner <> nil then
  Owner.RemoveComponent(Self);

Básicamente, cuando una componente se destruye, repasa su lista de componentes (los que posee), destruyendo cada uno. El código de arriba muestra que al destruirse, una componente se quita ella misma de la lista de componentes de su dueño, rompiendo, por así decirlo, el contrato de propiedad. Cuando ese dueño eventualmente se destruya, no tendrá a la componente en su lista y por tanto no habrá ningún intento por destruir algo que ya no existe.

// Saludos

zvf 08-04-2006 02:04:20

He puesto excepciones por todos lados, y no lo puedo ocultar, porque lo hace despues del ultimo end de la ejecucion, y espera que de nuevo presione o de un click en un label para volverlo a lanzar, pero no lo lanza siempre, por eso no puedo identificar cuando se lanza, es aleatorio.

Lo que yo quisiera seria que no los mostrara y que el sentido de mi programa siga como hasta hoy.

¿Se puede hacer esto?

zvf 08-04-2006 17:55:40

Una pregunta, al correrlo paso a paso, me dice que el archivo:
ZAbstractRODDataset.pas no lo encuentra.

¿Si tiene esto algo que ver con mi problema?

Lepe 08-04-2006 22:54:02

no creo. aunque puede que sea una de las consultas de Zeos la que se vea afectada por el fallo del programa.

El problema está en el código, y quizás sea un efecto colateral de alguna de tus acciones, por eso es tan dificil de localizar.

¿Querer ocultarlo? Si vas en el coche y de repente se para, le vuelves a dar a la llave y sigue funcionando, ¿cómo se puede ocultar ese fallo?

Saludos

roman 09-04-2006 03:10:19

Cita:

Empezado por Lepe
¿Querer ocultarlo? Si vas en el coche y de repente se para, le vuelves a dar a la llave y sigue funcionando, ¿cómo se puede ocultar ese fallo?

¡Caray! Es justo lo que me pasó hace tres o cuatro días. Como venía de bajada puede orillarme y detenerme. Al cabo de dos o tres intentos encendió nuevamente. Aun no he mandado revisarlo, sospecho de la batería pero como ha funcionado.. :o

// Saludos

Lepe 09-04-2006 17:17:52

Cita:

Empezado por roman
¡Caray! Es justo lo que me pasó hace tres o cuatro días. Como venía de bajada puede orillarme y detenerme. Al cabo de dos o tres intentos encendió nuevamente. Aun no he mandado revisarlo, sospecho de la batería pero como ha funcionado.. :o

// Saludos

Afortunadamente un programa que tú haces puedes modificarlo tú mismo. No creo que estes diciendo que el error de zvf deba obviarse ..., no es tu estilo ;).

Ya que hablamos de mecánica... de la bateria fijo que no es, ya que una vez que está en funcionamiento, la batería no hace nada (sino recargarse). Cuando hace su función es al tiempo de arrancar el vehículo.

Bien podría ser de "pelusas" en el carburador (motores de gasolina) que no dejen pasar la cantidad de gasolina necesaria, filtros de aire muy sucios que no dejan pasar el aire para realizar la mezcla, bujias deterioradas, etc.

Un saludo aceitoso ;)

zvf 10-04-2006 21:04:59

Ya quite muchisimas lineas de codigo, para dejar solo la parte en donde se genera el error y ya la tengo, vean son 4 procedimientos con una tabla que tengo en una base de datos.

Me gustaria enviarles los procedimientos nuevamente para que puedan checar con menos lineas de codigo, para ver si me pueden ayudar a encontrar el error.

Solo que veo que este hilo ya tiene muchas consultas, ¿podrian borrarlas para empezar de nuevo?

zvf 11-04-2006 01:27:05

Bien, el codigo que ahora tengo es el siguiente:

Tengo una tabla de una base de datos llamada categorias, esta tabla guarda lo siguiente:

Es un conjunto de categorias por ejemplo tengo:

Lacteos y dentro de lacteos tengo yogurth y leche.
En otra categoria tengo Carnes frias y dentro de ella tengo jamon y salchichas, de tal manera que la tabla para conocer los descendientes de cada categoria es la siguiente:

cat_nivel : guarda el nivel de la categoria (Lacteos es nivel 1 y sus descendientes son nivel 2 y asi consecutivamente cada nivel)

cat_codigo: para cada nivel, cada categoria tiene un codigo para identificarla, lacteos tiene el codigo 1(nivel 1), carnes frias codigo 2(nivel1), leche codigo 1(nivel2), yogurth codigo 2(nivel2), etc...

cat_padre: guarda el codigo del la categoria de la cual son descendientes, por ejemplo el padre de yogurth y leche es el numero 1, que pertenece a la categoria Lacteos.

cat_descripcion : guarda el nombre de la categoria, por ejemplo Lacteos.

Bien, a cotinuacion pondre cada uno de los 4 procedimientos que mando llamar:

zvf 11-04-2006 01:56:43

El procedimiento para crear los botones es el siguiente:
Código Delphi [-]
Procedure TFPrincipal.CreaBoton;
  var NewBoton : TLabel;
      nombre : string;
      scontador:string;
   begin
       if (band = 0) then  //PRIMER BOTON QUE CREA
               begin
               margen_izq := margen_izq_ini;
               margen_sup := margen_sup_ini;
               band := 1;
               end
        else
               begin
                margen_izq := margen_izq_ant;
                margen_sup := margen_sup_ant + alto_boton + margen_sup_ini;
                if (margen_sup > margen_inf) then
                    begin
                     margen_izq := margen_izq + margen_izq_ini;
                     margen_izq := margen_izq + ancho_boton;
                     margen_sup := margen_sup_ini;
                    end;
               end;
     with NewBoton do
        begin
        NewBoton := TLabel.create(FPrincipal.GroupBoxProd1);
        Parent := FPrincipal.GroupBoxProd1;
        scontador:= IntToStr (contador);
        nombre:= 'Boton';
        Name := nombre+scontador;
        Color:= clMoneyGreen;
        Width := ancho_boton;
        Height := alto_boton;
        Left := margen_izq;
        Autosize := false;
        Top := margen_sup;
        Caption := varCaption;
        OnClick := mostrar_productos;
        margen_izq_ant := margen_izq;
        margen_sup_ant := margen_sup;
      end; //fin del con hacer
  end;
//////  FIN DEL PROCEDIMIENTO CREAR UN BOTON EN TIEMPO DE EJECUCION   /////////

zvf 11-04-2006 01:57:46

El procedimiento para destruirlo es :
Código Delphi [-]
procedure TFPrincipal.DestruirBotones;
  var i, botonesCreados:integer;
begin
  botonesCreados:=FPrincipal.GroupBoxProd1.ControlCount;
 for i:=botonesCreados-1 downto 0 do
       begin
       FPrincipal.GroupBoxProd1.Controls[i].Free;
       end;
 inicializa;
end;

zvf 11-04-2006 01:59:47

El procedimiento siguiente, se manda llamar al dar click en un tlabel:

Código Delphi [-]
procedure TFPrincipal.mostrar_productos(sender : TObject);
var consulta,seleccionado : string;
    avanza,pos : integer;
begin
   pos:= -1;
   seleccionado:=(Sender as TLabel).Caption;
   // busca el seleccionado en el arr_descripciones, ya que lo encuentra ve el cod. en arr_codigos
   avanza :=0;
   while avanza < pos_descripciones do
    begin
     if arr_descripciones[avanza] = seleccionado then
       begin
         pos := avanza;
         avanza := pos_descripciones;
       end;
     avanza := avanza+1;
    end;
    nivel := nivel+1;
    padre := strtoint(arr_codigos[pos]);
    mostrar_productos1;
end;

zvf 11-04-2006 02:01:11

El procedimiento mostrar_productos1 es el que destruye los label existentes y crea nuevos con las categorias, ya dandole un nivel y un padre:

Código Delphi [-]
procedure TFPrincipal.mostrar_productos1;
var  avanza: integer;
     snivel,spadre,sclasif, consulta : string;
begin
       snivel := IntToStr (nivel);
       spadre := IntToStr (padre);
      //CONSULTA EN CATEGORIAS
      ZQNueva.SQL.Clear;
      consulta := 'SELECT `cat_descripcion`, `cat_codigo` FROM `categorias` WHERE `cat_nivel`= '+ #39 +  snivel + #39 +' and `cat_padre`= '+ #39 +  spadre + #39 +';';
      ZQNueva.SQL.Add(consulta);
      ZQNueva.Open;
      if ZQNueva.RecordCount > 0 then
      begin
       pos_descripciones :=0;
       for avanza:=0 to 99 do
           BEGIN
           arr_descripciones[avanza]:='';
           arr_codigos[avanza]:='';
           END;
       while not ZQNueva.Eof do
       begin
        arr_descripciones[pos_descripciones]:= ZQNueva.Fields[0].AsString;
        arr_codigos [pos_descripciones]:= ZQNueva.Fields[1].AsString;
        pos_descripciones := pos_descripciones +1;
        ZQNueva.Next;
       end;
       DestruirBotones;
       for avanza:=0 to pos_descripciones-1 do
         begin
         Contador := Contador+1;
         varCaption:= arr_descripciones[avanza];
         CreaBoton;
         end;
     end
     else
       begin
       nivel := nivel-1;
       showMessage ('Categoria vacia');
       end;
end;
///////FIN DEL PROCEDIMIENTO MOSTRAR PRODUCTOS1  /////////////////////////////

zvf 11-04-2006 02:02:49

Si tienen tiempo, y lo checan, si ven algo extraño me dicen por favor.
Yo nose que es lo que pase, yo veo que el codigo esta bien, pero esos errores siguen apareciendo :( :( .

GRACIAS, DE ANTEMANO, GRACIAS POR SU COOPERACION Y AYUDA :rolleyes: .

Lepe 11-04-2006 16:01:26

Demasiadas variables, tantas que es imposible seguir el código. No usas parámetros para nada, sino que usas variables globales que despues tienes que adivinar si se ha modificado en algún sitio o no.

Código Delphi [-]
 if ZQNueva.RecordCount > 0 then
      begin
       DestruirBotones;
       contador := 0;
       while not ZQNueva.Eof do
       begin
          inc(contador);
          CreaBoton(contador, 
                    ZQnueva.Fields[0].AsString, 
                    ZQNueva.Fields[1].AsString
                   );
          ZQNueva.Next;
       end;
     end
     else
       begin
       nivel := nivel-1;
       showMessage ('Categoria vacia');
       end;

No necesitas arr_codigos, ni arr_descripciones, amén que solo tiene 99 posiciones; si la consulta da 200 resultados, adios arrays.

Código Delphi [-]
scontador:= IntToStr (contador);
        nombre:= 'Boton';
        Name := nombre+scontador;
Código Delphi [-]
Name := 'Boton'+ inttostr(contador)
Es lo mismo ¿si o si? ;) Pues no, son 2 variables menos :p

Variables globales.... ninguna.

El código lo puedes guardar en el Label.Tag.

Saludos

Lepe 11-04-2006 16:18:10

Código Delphi [-]
procedure TFPrincipal.mostrar_productos(sender : TObject);
var padre: integer;
begin
//   seleccionado:=(Sender as TLabel).Caption;
// no sé para que se usa "seleccionado"

//no entiendo de donde viene nivel, pero en fins....
   nivel := nivel +1;
   padre := (Sender as Tlabel).tag;
   mostrar_productos1(inttostr(padre),inttostr(nivel));
end;

Saludos

zvf 11-04-2006 17:35:00

¿ Ustedes como harian un codigo para hacer esto que necesito y que funcione?

No importa que lo tenga que cambiar, solo quiero que no mande estos errores.

Y lo que necesito que haga es eso, de un tabla de una base de datos que describí arriba, cree los tlabel en tiempo de ejecucion, y al dar click en uno, muestre sus descendientes.

¿ Tienen sugerencias de como hacerlo?

Lepe 12-04-2006 09:18:25

Te paso un programita adaptado para tí.

Verás que solo difiere en 2 cositas.
- Uso una "lista" para almacenar los labels que se crean y poder destruirlos comodamente.
- Añado efecto de hyperlink a los labels.... ya una pijotada :D

Por lo demás es tu codigo.

Saludos

guiweb 02-05-2006 17:35:30

un Result??
 
Una consulta. pimero que todo, no he tenido el tiempo de lerme el codigo, pero a mi me ocurrio un error bastante similar "Abstract Error", esto se ocacionaba por culpa de una Funcion que pedia le devolviese un boolean, asi que lo unico que hice fue colocar un Result:= False; y se me acabo el problema, ojala que esto te pueda ayudar... aveces las cosas mas Obvias se nos escapan

ElielEgo 08-09-2010 18:50:33

Hola mmmm se que quizá estan dando respuesta a la pregunta de alguien más, pero yo tengo el mismo problema y según yo no lo estoy haciendo de una forma erronea.

Les comento, Tengo una forma donde lo único que tengo es un TXMLDocument (name: xml_doc) con el que leo un cuestionario en xml. Este cuestionario por necesidades del mismo varía el número de respuestas que a efectos del sistema se convertirán en radiobuttons. Por tal motivo debo generarlos de manera dinámica cada vez que se cargue una pregunta. Sin embargo en ocasiones y no siempre en el mismo momento me marca este tipo de errores cuando genero los nuevos elementos.

este es mi código

Código Delphi [-]
procedure Tfrm_quiz.cargaPregunta(index:integer);
var
  pregunta:  IXMLNode ;
  arriba, i, max_node_child:integer;
  boton : TbitBtn;
  radio: TRadioButton;
  control : TControl;
  _label : Tlabel;
begin

  boton := nil;
  radio := nil;
  _label := nil;
  control := nil;
  //Index se refiere al número de nodo que leo del xml es decir el reactivo
  if (index <> 0) then
  begin    
    for i:= 0 to (self.ControlCount -1) do
    begin       
        control := self.Controls[0];//Siempre uso el 0 porque es como ir eliminando el primero que encuentra
        freeandnil(control);
    end;
  end;

  pregunta:= self.xml_doc.DocumentElement.ChildNodes[index];
  _label := TLabel.Create(nil);

  with _label do
    begin
      left := 16;
      top:= 16;
      caption := pregunta.ChildNodes['reactivo'].Text;
      parent:=self;
    end;


  max_node_child := pregunta.ChildNodes.Count - 1;
  arriba := 64;
  for i:= 1 to max_node_child do
  begin
    radio := TRadioButton.Create(nil);
    with radio do
    begin
      left := 16;
      top:= arriba;
      arriba := arriba +30;
      width := 560;
      name := 'rdb_'+inttostr(i);
      helpKeyword := pregunta.ChildNodes[i].Attributes['etiqueta'];
      caption := pregunta.ChildNodes[i].Text;
      onClick := evaluaClick;
      parent:=self;
    end;
  end;

  if (index < self.max_node -1) then
  begin
    boton := TbitBtn.Create (nil);
    with boton do
    begin
      caption := 'Siguiente';
      left := 506;
      top := 640;
      name := 'btn_siguiente';
      OnClick := BitBtn1Click;
      parent:=self;
    end;
  end
  else
  begin    
    boton := TbitBtn.Create (nil);
    with boton do
    begin
      caption := 'Finalizar';
      left := 506;
      top := 640;
      name := 'btn_finalizar';
      OnClick := finaliza;
      parent:=self;
    end;
  end;
end;

Muchas gracias a quien me pueda ayudar y seguimos en contacto por aca...


La franja horaria es GMT +2. Ahora son las 05:54:14.

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