Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Varios (https://www.clubdelphi.com/foros/forumdisplay.php?f=11)
-   -   Gmlib Gmmarker (https://www.clubdelphi.com/foros/showthread.php?t=92833)

DrakStorm 16-02-2018 20:58:12

Gmlib Gmmarker
 
Buenas tardes a todos y desde ya muchas gracias por tomarse el tiempo de tratar de solucionar mi inquietud.

Paso a comentar mi problema, estoy utilizando GMLIB en RAD Studio XE7, el componente funciona perfecto, pero tengo un problema cuando aplico el procedimiento CLEAR en el GMMarker, lo que pasa es que el procedimiento limpia todos los marcadores que genere anteriormente, pero no borra la cola es decir cuando genero el primer marcador el ID de la cola es el 0 (cero) y el siguiente es el 1, hasta el momento todo perfecto, cuando aplico el CLEAR, dejo de visualizar esos marcadores en el mapa, pero el siguiente marcador que genero tiene como ID 2 y no 0 (cero), y creo que el problema es que esos marcadores no se visualizan pero siguen estando en la cola y guardan el nombre que se puso al marcador.

Me gustaría saber si tengo alguna manera de borrar la cola que genera el GMMarker o si hay alguna manera de resetear esa cola.

AYUDDAAAAA!!!!!!!
Muchas gracias

Neftali [Germán.Estévez] 19-02-2018 10:23:47

Cita:

Empezado por DrakStorm (Mensaje 524595)
cuando aplico el procedimiento CLEAR en el GMMarker, lo que pasa es que el procedimiento limpia todos los marcadores que genere anteriormente, pero no borra la cola

GMMarker es una lista y cuando haces el Clear si se borran todos los elementos de la lista y se libera la memoria de los elementos.
Si haces un Count verás que la lista tiene 0 elementos.

Cita:

Empezado por DrakStorm (Mensaje 524595)
es decir cuando genero el primer marcador el ID de la cola es el 0 (cero) y el siguiente es el 1, hasta el momento todo perfecto, cuando aplico el CLEAR, pero el siguiente marcador que genero tiene como ID 2 y no 0 (cero)

Otra cosa diferente y que estás confundiendo es el ID que se asigna a cada elemento, que no tiene porqué resetearse cuando haces el Clear. Ese ID es el que se va incrementando y aunque hagas el Clear no se pone a cero (y no tiene porqué ponerse). Ese ID identifica a cada elemento, y no tiene resetearse.

Según lo que estés haciendo y para qué estés utilizando ese valor, puede usar de forma alternativa GMMarker.Count.
Otra opción es Marker.ZIndex, que parece que si que se comporta como deseas, de todas formas habrá que ver qué pasa con esta propiedad cuando borres elementos existentes, crees elementos nuevos,...

Una última opción para que el ID se comporte como deseas (aunque no la veo la más adecuada) es liberar la lista (GMMarker) y volver a crearla. De esa forma, el ID si se reinicia a cero.

Código Delphi [-]
  GMMarker1.Free;
  GMMarker1 := TGMMarker.Create(Self);
  //...   asignar otras propiedades

DrakStorm 19-02-2018 15:25:21

Buen día Neftali, muchas gracias por tu respuesta y tu tiempo.
Paso a comentar el problema pero ahora te muestro el código para que veas lo que estoy haciendo y asi entiendas mejor el por que de mi pregunta.

Código Delphi [-]

// GENERO LOS PUNTOS EN EL MAPA
procedure TFMapa.Button1Click(Sender: TObject);

var Marcador : TMarker;

begin

  PrincipalF.AQofi.First;

while not PrincipalF.AQofi.Eof do

    Begin

    if Principalf.AQofi.FieldByName('lat').value <> null  then


    begin
    Lat4 := Principalf.AQofi.FieldByName('lat').Value;
    Lng4 := Principalf.AQofi.FieldByName('lng').Value;
    marcador := GMMark2.Add(Lat4, Lng4, Principalf.AQofi.FieldByName('id').AsString);
    marcador.Icon := 'C:\ComSoft\puntoazul.png';
    end;
    PrincipalF.AQofi.Next;
    End;

     GMMark2.ZoomToPoints;

end;


// Cuando marco los puntos al hacerles click muestro en unos edit la informacion guardada en la DB referente al punto seleccionado
procedure TFMapa.GMMark2Click(Sender: TObject; LatLng: TLatLng; Index: Integer;
  LinkedComponent: TLinkedComponent);
begin


 if GMMark2.Count > 0 then begin

 // ACA SE GENERA EL ERROR
  AQmap.Active := false;
// CUANDO HAGO CLICK EN EL MARCADOR EL linkedcomponent.id ME DA EL VALOR CORRECTO PERO GMMark2.items[linkedcomponent.id].title QUEDA VACIO COMO SI EL MARCADOR NO TUVIERA UN TITLE
  AQmap.SQL.Text := 'select id, tipodelito, otros from oficios WHERE id="'+GMMark2.items[linkedcomponent.id].title+'"';
  AQmap.Active := true;

  Edit1.Text := AQmap.FieldByName('id').AsString;
  Edit2.Text := AQmap.FieldByName('tipodelito').AsString;
  Edit3.Text := AQmap.FieldByName('otros').AsString;


 end;
end;

// Limpio los puntos del mapa

procedure TFMapa.Button2Click(Sender: TObject);

begin

if GMMark2.Count > 0 then
    Begin
    GMMark2.clear;

    End;
end;

Cuando hago el clear y vuelvo a generar los puntos funciona perfecto ahora cuando le quiero hacer click en uno de los puntos me da el siguiente error (Argument out of range) y la verdad es que no entiendo por que.

Desde ya muchas gracias por la ayuda y espero que se entienda el problema o que puedas ver que es lo que estoy haciendo mal. la verdad es que soy nuevo con GMlib pero lo necesito urgente para el trabajo.

DrakStorm 19-02-2018 16:00:05

Cita:

Empezado por DrakStorm (Mensaje 524633)

[delphi]


// Cuando marco los puntos al hacerles click muestro en unos edit la informacion guardada en la DB referente al punto seleccionado
procedure TFMapa.GMMark2Click(Sender: TObject; LatLng: TLatLng; Index: Integer;
LinkedComponent: TLinkedComponent);
begin


if GMMark2.Count > 0 then begin

// ACA SE GENERA EL ERROR
AQmap.Active := false;
// LA PRIMERA VEZ QUE MUESTRO LOS PUNTOS FUNCIONA PERFECTO, CUANDO HAGO EL CLEAR Y VUELVO A CARGAR LOS PUNTOS ME PASA LO SIGUIENTE
// CUANDO HAGO CLICK EN EL MARCADOR EL linkedcomponent.id ME DA EL VALOR CORRECTO PERO GMMark2.items[linkedcomponent.id].title QUEDA VACIO COMO SI EL MARCADOR NO TUVIERA UN TITLE
AQmap.SQL.Text := 'select id, tipodelito, otros from oficios WHERE id="'+GMMark2.items[linkedcomponent.id].title+'"';
AQmap.Active := true;

Edit1.Text := AQmap.FieldByName('id').AsString;
Edit2.Text := AQmap.FieldByName('tipodelito').AsString;
Edit3.Text := AQmap.FieldByName('otros').AsString;


end;
end;

Disculpas por pegar de nuevo pero no podía editar el mensaje.

Neftali [Germán.Estévez] 19-02-2018 18:46:32

El problema es que estás utilizando el ID como índice para realizar la búsqueda en la lista, y tal como te he comnentado esa condición no siempre es cierta (por ejemplo, cuando has hecho un Clear).

Implementa una busqueda por título (recorriendo la lista de Marcas); A no ser que tengas una gran cantidad de marcas, recorrer la lista secuencialmente debe ser inmediato. Si tuvieras miuchísimas, siempre puedes hacer una estructura paraleta que te mantenga ID/Indice.

DrakStorm 19-02-2018 19:01:18

Cita:

Empezado por Neftali [Germán.Estévez] (Mensaje 524636)
El problema es que estás utilizando el ID como índice para realizar la búsqueda en la lista, y tal como te he comnentado esa condición no siempre es cierta (por ejemplo, cuando has hecho un Clear).

Implementa una busqueda por título (recorriendo la lista de Marcas); A no ser que tengas una gran cantidad de marcas, recorrer la lista secuencialmente debe ser inmediato. Si tuvieras miuchísimas, siempre puedes hacer una estructura paraleta que te mantenga ID/Indice.

Creo que lo que me dices es lo que estoy haciendo yo al marcador le pongo de titulo el id que tengo en la DB donde tengo los datos de ese marcador y cuando hago click en el marcador quiero recuperar el titulo de ese marcador para poder traer los campos de la DB asociados a ese id.

La única manera que tengo de saber a que marcador se refiere es con linkedcomponent.id eso me da el valor del id del marcador y en base a ese id pregunto cual es el titulo con esto GMMark2.items[linkedcomponent.id].title ahora el linkedcomponent.id me da el valor correcto del marcador pero GMMark2.items[linkedcomponent.id].title no me da el title de ese marcador.

Este error solo se genera después de aplicar el clear, en la primera carga si me devuelve el title y puedo realizar la busqueda en la DB, nose por que en la segunda carga después de aplicar el clear GMMark2.items[linkedcomponent.id].title me devuelve un resultado vació y ahí se genera el argument out of rage.

linkedcomponent.id si trae el id correcto del marcador en todo momento, pero cuando consulto por el title de ese marcador me lo trae vacio

perdon si soy repetitivo es que nose como explicar mejor lo que me esta sucediendo
Muchas gracias

DrakStorm 19-02-2018 19:57:20

En la imagen trato de ser mas explicativo jajajaj
esto pasa solamente despues de aplicar el clear en la primera carga funciona perfecto

https://ibb.co/bHSMfn


dejo el link de la imagen por que no tengo permitido subir imágenes al foro todavía

Neftali [Germán.Estévez] 19-02-2018 20:16:18

En la primera carga el ID de cada marca coincide con su índice en la lista:
Lista:


Index=0 Marca.ID=0
Index=1 Marca.ID=1
Index=2 Marca.ID=2


(la primera vez, el ID de cada marca -segunda columna- coincide con el INDEX de la lista, por eso no tienes problemas en acceder)

Después de hacer el clear, Los índices de la vuelven a comenzar por 0, mientras que el ID de las marcas sigue la progresión anterior. La lista después de hacer el Clear y crear nuevas marcas queda así:


Index=0 Marca.ID=3
Index=1 Marca.ID=4
Index=2 Marca.ID=5


Por eso, cuando intentas acceder a los elementos de la lista así (utilizando el ID):

Código Delphi [-]
  ...
  GMMark2.items[linkedcomponent.id].title
  ...

Utilizando, por ejemplo la marca con ID=4, te da un "out of rande", porque el íncide de la lista=4 no existe.

DrakStorm 19-02-2018 20:21:03

realice una prueba de la siguiente manera

showmessage (GMMark2.items[linkedcomponent.id].title)
la primera carga suponiendo que tengo solo una marca linkedcomponent.id tiene valor 0 y me trae el titilo del marcador correctamente.
despues de aplicar el clear hago esto showmessage (GMMark2.items[linkedcomponent.id].title) y el linkedcomponent.id tiene valor 1 y el titulo del marcador da error.

Despues de eso puse este mensaje y me mostró el titulo correctamente
showmessage (GMMark2.items[0].title)

En resumen cuando hago el clear me borra los marcadores y les genera un nuevo id a cada uno es decir si tengo 4 marcadores los genera desde el 0 al 3 pero el linkedcomponent.id no se resetea y cuando hago el clear en lugar de que el id del marcador valla del 0 al 3 va del 4 al 7.

hay alguna manera de resetear eso? por la verdad ya estoy perdido.

DrakStorm 19-02-2018 20:24:06

Cita:

Empezado por Neftali [Germán.Estévez] (Mensaje 524639)
En la primera carga el ID de cada marca coincide con su índice en la lista:
Lista:


Index=0 Marca.ID=0
Index=1 Marca.ID=1
Index=2 Marca.ID=2


(la primera vez, el ID de cada marca -segunda columna- coincide con el INDEX de la lista, por eso no tienes problemas en acceder)

Después de hacer el clear, Los índices de la vuelven a comenzar por 0, mientras que el ID de las marcas sigue la progresión anterior. La lista después de hacer el Clear y crear nuevas marcas queda así:


Index=0 Marca.ID=3
Index=1 Marca.ID=4
Index=2 Marca.ID=5


Por eso, cuando intentas acceder a los elementos de la lista así (utilizando el ID):

Código Delphi [-]
  ...
  GMMark2.items[linkedcomponent.id].title
  ...

Utilizando, por ejemplo la marca con ID=4, te da un "out of rande", porque el íncide de la lista=4 no existe.

exactamente acabo de escribir lo que dices pero mas a lo bestia, muchas gracias por tu atención y tu predisposición.

Ahora hay alguna manera para que el id de la marca coincida con el index?

DrakStorm 19-02-2018 20:56:36

Muchas gracias por tu ayuda lo solucione de la siguiente manera

Código Delphi [-]

procedure TFMapa.GMMark2Click(Sender: TObject; LatLng: TLatLng; Index: Integer;
  LinkedComponent: TLinkedComponent);
begin


 if GMMark2.Count > 0 then
    begin
     if CMap > 1 then
       begin
        AQmap.Active := false;
        AQmap.SQL.Text := 'select id, tipodelito, otros from oficios WHERE id="'+GMMark2.items[linkedcomponent.id - F].title+'"';
        AQmap.Active := true;
       end
        else
       begin
        AQmap.Active := false;
        AQmap.SQL.Text := 'select id, tipodelito, otros from oficios WHERE id="'+GMMark2.items[linkedcomponent.id].title+'"';
        AQmap.Active := true;
       end;

        Edit1.Text := AQmap.FieldByName('id').AsString;
        Edit2.Text := AQmap.FieldByName('tipodelito').AsString;
        Edit3.Text := AQmap.FieldByName('otros').AsString;

    end;



end;

procedure TFMapa.Button1Click(Sender: TObject);

var Marcador : TMarker;

begin

  PrincipalF.AQofi.First;

while not PrincipalF.AQofi.Eof do

    Begin

    if Principalf.AQofi.FieldByName('lat').value <> null  then
        begin
          Lat4 := Principalf.AQofi.FieldByName('lat').Value;
          Lng4 := Principalf.AQofi.FieldByName('lng').Value;
          NombreMark := Principalf.AQofi.FieldByName('id').AsString;
          marcador := GMMark2.Add(Lat4, Lng4, NombreMark);
          marcador.Icon := 'C:\ComSoft\puntoazul.png';
          I := I + 1;
        end;

     PrincipalF.AQofi.Next;
    End;
     CMap := CMap + 1;
     GMMark2.ZoomToPoints;

end;

procedure TFMapa.Button2Click(Sender: TObject);

begin

if GMMark2.Count > 0 then
    Begin
    F := I;
    GMMark2.clear;
    close;
    End;
end;

Lo que hago es contar los marcadores que se generan y luego se los resto al id del marcador solo después de la primera carga.

Se que para programadores mas expertos esto es un aborto de la naturaleza pero es lo único que se me ocurrió a mi, si tienes una solución mucho mas optima te lo agradecería mucho.

Desde ya muchas gracias por toda tu ayuda estaba muy trabado con ese tema.

Neftali [Germán.Estévez] 20-02-2018 10:00:09

Cita:

Empezado por DrakStorm (Mensaje 524642)
...si tienes una solución mucho mas optima te lo agradecería mucho.

En el mensaje anterior te comenté algunas opciones.

La primera a probar sería utilizando la popiedad ZIndex de cada marca en lugar del ID. Parece que ese índice sí se resetea al hacer el Clear.
Código Delphi [-]

  GMMark2.items[linkedcomponent.ZIndex].title

La segunda (y ahora me acabo de dar cuenta) es utilizar d9irectamente la propiedad de la marca, en lugar de buscar en la lista el título, ya que también la tiene. Es decir, utilizar esto para acceder al título:

Código Delphi [-]
  AQmap.SQL.Text := 'select id, tipodelito, otros from oficios WHERE id="'+TMarker(linkedcomponent).title+'"';
Y en todo caso, comprobar antes que linkedcomponent es un TMarker.

La tercera, que también te he comentado, es usar una función para buscar el título que esperas sin usar el ID.

Código Delphi [-]
function GetTitle(GMMarker:TGMMarker; LinkedComponent: TLinkedComponent):string;
var
  i:integer;
begin
  Result := '';
  for i := 0 to (GMMarker.Count - 1) do begin
    if (GMMarker.Items[i] = LinkedComponent) then begin
      Result := GMMarker.Items[i].Title;
      Break;
    end;
  end;
end;

En este caso usarías algo así:

Código Delphi [-]
AQmap.SQL.Text := 'select id, tipodelito, otros from oficios WHERE id="'+GetTitle(GMMark2, linkedcomponent)+'"';

Más o menos son las que se me ocurren.

DrakStorm 20-02-2018 15:17:44

Cita:

Empezado por Neftali [Germán.Estévez] (Mensaje 524647)
En el mensaje anterior te comenté algunas opciones.

La primera a probar sería utilizando la popiedad ZIndex de cada marca en lugar del ID. Parece que ese índice sí se resetea al hacer el Clear.
Código Delphi [-]

  GMMark2.items[linkedcomponent.ZIndex].title

La segunda (y ahora me acabo de dar cuenta) es utilizar d9irectamente la propiedad de la marca, en lugar de buscar en la lista el título, ya que también la tiene. Es decir, utilizar esto para acceder al título:

Código Delphi [-]
  AQmap.SQL.Text := 'select id, tipodelito, otros from oficios WHERE id="'+TMarker(linkedcomponent).title+'"';
Y en todo caso, comprobar antes que linkedcomponent es un TMarker.

La tercera, que también te he comentado, es usar una función para buscar el título que esperas sin usar el ID.

Código Delphi [-]
function GetTitle(GMMarker:TGMMarker; LinkedComponent: TLinkedComponent):string;
var
  i:integer;
begin
  Result := '';
  for i := 0 to (GMMarker.Count - 1) do begin
    if (GMMarker.Items[i] = LinkedComponent) then begin
      Result := GMMarker.Items[i].Title;
      Break;
    end;
  end;
end;

En este caso usarías algo así:

Código Delphi [-]
AQmap.SQL.Text := 'select id, tipodelito, otros from oficios WHERE id="'+GetTitle(GMMark2, linkedcomponent)+'"';

Más o menos son las que se me ocurren.


Paso a comentar los resultados de las soluciones que me aportaste.

Primera solución: tira error (TLinkedComponent does not contain a member name ZIndex).

Segunda solución: esta funciona perfecto y creo que para mi caso es la mas practica.

Tercera solución: funciona perfecto pero creo que no es la mas acorde para mi caso en particular.

Bueno espero que este post ayude a alguien mas también, y desde ya mas que agradecido por todas tus respuestas y el tiempo que le dedicaste a mi tema, MUCHAS PERO MUCHAS Gracias Neftali [Germán.Estévez] sos un crack.

DrakStorm 20-02-2018 16:13:00

Cita:

Empezado por DrakStorm (Mensaje 524659)
Primera solución: tira error (TLinkedComponent does not contain a member name ZIndex).

Corrijo ZIndex no funciona con GMMarker pero si funciona perfecto con TMarker.

Neftali [Germán.Estévez] 20-02-2018 17:19:32

Cita:

Empezado por DrakStorm (Mensaje 524659)
Primera solución: tira error (TLinkedComponent does not contain a member name ZIndex).

Tienes que hacer un CAST como se hace en la segunda...
Aunque si la segunda te funciona, coincido en que parece la más adecuada y directa.

Código Delphi [-]
  GMMark2.items[TMarker(linkedcomponent).ZIndex].title

Neftali [Germán.Estévez] 20-02-2018 17:20:15

Cita:

Empezado por DrakStorm (Mensaje 524663)
Corrijo ZIndex no funciona con GMMarker pero si funciona perfecto con TMarker.

^\||/^\||/^\||/^\||/
No lo había leído antes de escribir el último mensaje.


La franja horaria es GMT +2. Ahora son las 03:05:27.

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