Restrospectiva del curso de desarrollo de gvSIG 2.0

Recientemente se ha terminado la primera edición del curso de desarrollo de gvSIG 2.0 a través de la plataforma de e-learning de la Asociación gvSIG: gvSIG Training. He tenido el gusto de participar como alumno y como una forma de revisar mi experiencia en el mismo, arranqué en el foro del curso un hilo con un pequeño análisis sobre cómo me ha ido, de forma que más allá de la encuesta de satisfacción que también hemos hecho, reflexionáramos sobre lo bueno y lo malo del curso para intentar mejorar las próximas ediciones del mismo. Comparto el mensaje en el blog para mostraros cómo ha ido para que tengáis otra visión (la mía vaya) de un curso de e-learning sobre gvSIG.

Desde luego son mis opiniones y otros compañeros han compartido algunas y otras no. También es cierto que dado que ya venía de programar en gvSIG 1.x hace tiempo, conocía las herramientas de desarrollo (especialmente maven) y mi punto de partida estába más «adelantado» que el de otros compañeros, aún así, creo que os puede resultar de interés.

Hola, me gustaría arrancar un hilo de retrospectiva sobre el curso, ahora que ya está acabado. Voy a seguir el modelo de retrospectiva en estrella. Tal vez esté previsto algún cuestionario de evaluación en el curso pero con estas notas yo voy por libre.

Seguir haciendo:

  • Generar material de tan alta calidad, con un buen balance entre los pasos guiados y los ejercicios un poco más abiertos donde hay que pensar un poquito más en lo que se está haciendo y lo que se está pidiendo.
  • Fomentar la participación en los foros, no solo en comunicación profesor-alumno sino sobre todo entre alumnos.
  • Ofrecer los ejercicios resueltos para poder “reengancharse” si te atascas en algún ejercicio.

Menos de:

A mí el parón de verano no me ha fastidiado mucho (se paró en Agosto, aunque no estaba previsto), aunque preferiría que no se hubiera dado. Entiendo que fuera necesario y por suerte al tener todo el material disponible yo al menos pude hacer casi todo sin problemas pero entiendo que en un curso de este tipo es mejor no tener un parón porque se puede uno sentir que se ha bajado del tren en marcha.

Más de:

Seguir mejorando y ampliando el excelente material.

Parar de hacer:

Nada en especial, creo que todo en el curso está bien, tal vez el tener solo un profesor disponible sea limitante aunque para el número de alumnos de esta edición creo que con un profesor ha sido suficiente.

Empezar a hacer:

Se me ocurren:

  • Organizar un chat semanal, no para resolver dudas técnicas, que para eso están los foros y van muy bien, sino para contar qué tal ha ido la semana entre los alumnos, dónde han tenido problemas, qué cosas les han gustado más, etc.
  • Proponer ejercicios de ampliación, sin dar las respuestas. Algo así como retos, que permitan explorar un poco más en cada tema para aquellos que puedan hacerlos con más facilidad.
  • Tal vez crear un repositorio en el que ir subiendo el código del curso lección a lección, de forma que tras la fecha límite simplemente baste con hacer un update del proyecto para ver los cambios pudiendo explorar las diferencias entre versiones y tal.

Resumiendo

Yo por mi parte salgo del curso contento. He profundizado en las novedades de desarrollo en gvSIG 2.0, aprendiendo bastantes cosas nuevas. Por mi trabajo actual hace tiempo que no desarrollo sobre gvSIG, aunque obviamente estoy al tanto de lo que se ha ido haciendo en el proyecto.

El material aportado me parece de muy alta calidad, y aunque ha habido problemas con la gente que desarrollaba en Windows, sus problemas también han ayudado a pulir el entorno de desarrollo en esta plataforma por lo que (espero sirva de compensación) su esfuerzo no ha sido en balde.

Un saludo a todos, espero que el curso os resulte de utilidad en vuestros proyectos profesionales. Os animo también a que si seguís desarrollando en gvSIG consideréis cuando os encontréis con algún fallo, el reportarlo al tracker de bugs y si os animáis, intentéis resolverlo. ¡Por supuesto contad con la comunidad de desarrollo en las listas!

Posted in development, gvSIG Desktop, opinion, spanish | Tagged , , | 6 Comments

gvSIG Batoví, the first gvSIG distribution for Education

The Minister of Transport and Public Works, Enrique Pintado, presented gvSIG Batoví, the first Uruguayan distribution that has given rise to gvSIG Educa, on Thursday, 6 September 2012.

gvSIG Educa is a customization of the gvSIG Desktop Open Source GIS, adapted as a tool for the education of issues that have a geographic component. The aim of gvSIG Educa is to provide educators with a tool that helps students to analyse and understand space, and which can be adapted to different levels or education systems. gvSIG Educa facilitates learning by letting students interact with the information, by adding a spatial component to the study of the material, and by facilitating the assimilation of concepts through visual tools such as thematic maps or helping to understand spatial relationships.

In this way, gvSIG Batoví is the beginning of an open source software that will be probably adapted and used in a lot of countries. gvSIG Batoví is a software promoted by the National Survey Department for CEIBAL Project, whereby primary and secondary education students will be able to access to educational information represented on maps.

“From the Ceibal Project implementation, the government seeks to promote policies that support the development and benefit of the education of children, our future and present of the country”, Pintado highlighted, specifying that by their geographical characteristics, Uruguay can’t produce goods on a large scale, “but we can generate unlimited knowledge without any limit”.

During the presentation of this new tool, event attended by the Undersecretary of the Ministry, Pablo Genta, the National Director of Surveying, Jorge Franco and the Dean of the Faculty of Engineering, Héctor Cancela, the Minister noted that “Uruguayan people can distinguish ourselves by the intelligence, capacity for innovating and research, and link that knowledge to development.” “And for that, this new software called ‘gvSIG Batoví’, will be fundamental, because it allows the Gurises to access to a immense universe of knowledge”, he said.

The “gvSIG Batoví” application is the result of the joint work between the National Survey Department, the Faculty of Engineering and the gvSIG Association, and students will be able to gain Geography knowledge with it, using the XO -low cost laptops-. It will be applied to other knowledge areas like History, Biology…

The most interesting thing is that the student or teacher can create their own thematic map from the different information layers. Whit this option, the knowledge by discovery is promoted, converting the cartographic work in a learning knowledge.

With “gvSIG Batoví”, a first group of thematic maps of the Uruguayan territory is offered, for example political and physical maps, population distribution, communication and transport infrastructure and land cover. The ease to access to these thematic maps -as plugins to be installed from the application- will allow to share cartography between teachers and students of the whole users community easily.

Beyond the educational field, the professional users of the gvSIG technology will be able to access to these new functionalities from plugins. It will be an easy way to share territorial information.

It should be pointed out that there will be a presentation and a workshop about gvSIG Batoví at the 4th Latin America and Caribbean gvSIG Conference, and 2nd Uruguayan gvSIG Conference.

Finally it’s important to highlight the emphasis in the collective of the project, where 4 entities participated in a coordinated way: the National Survey Department (of the MTOP – Uruguay), as promoter of the project; the gvSIG Association, as main developer of the application and other aspects (documentation, spreading…); Group of Geospatial Information Technologies of the Faculty of Engineering (UDELAR – Uruguay), as local part of the development; and the Ceibal Center as distribution and implementation manager at the Ceibal Project (Ceibal means “Educational Connectivity of Basic Information for online learning”, apart from referring to the national flower, the “ceibo”).

Posted in community, english, gvSIG Desktop, gvSIG Educa | 1 Comment

Nueva convocatoria de cursos gvSIG-Training

La Plataforma de Capacitación a Distancia gvSIG-Training anuncia que el proceso de inscripciones del segundo corte del 2012 para los siguientes cursos, que forman parte de la oferta del Programa de Certificación de la Asociación gvSIG da inicio según se detalla a continuación:

En la modalidad de Matrícula Restringida (por Cupos), con inscripciones abiertas a partir de hoy 05 de Septiembre:

* 4ª edición “gvSIG para usuarios en Español”. Duración: 10 semanas. Inicia: 08/10/2012. Programa de Certificaciones gvSIG: 90 Créditos.

* 3ª edición “Geoprocesamiento Avanzado: Sextante sobre gvSIG” en Español. Duración: 10 Semanas. Inicia: 24/09/2012. Programa de certificaciones gvSIG: 75 Créditos.

* 1ª y 2ª edición “Análisis de Redes con gvSIG en Italiano”. Duración: 2 semanas. Fechas de Inicio: 15/11/2012 y el 03/12/2012. Programa de certificaciones gvSIG: 20 Créditos.

* 1ª y 2ª edición “Extensión de Navtable y normalización de tablas de gvSIG en Italiano”. Duración: 1 semana. Fechas de Inicio: 19/11/2012 y el 17/12/2012. Programa de certificaciones gvSIG: 10 créditos.

* 1ª edición “PostGIS Avanzado, Base de Datos Espaciales PostgreSQL-PostGIS”. Duración: 9 semanas. Inicia: 08/10/2012. Programa de certificaciones IDE: 40 Créditos.

* 3ª Edición “gvSIG para usuarios en Italiano”.  Duración:  07 semanas.  Inicia:  22/10/2012.  Programa de Certificaciones gvSIG:  90 Créditos.

* 2ª y 3ª Edición “extensión 3D de gvSIG para usuarios en Español”.
Duración: 2 semanas. Inicia: 15/10/2012 y 05/11/2012. Programa de certificaciones gvSIG: 30 créditos.

En la modalidad de Matrícula Abierta (oferta permanente), con inscripciones abiertas a partir del hoy 05 de Septiembre:

* “Extensión de Navtable y normalización de tablas de gvSIG en Español”. Duración: 1 semana. Programa de certificaciones gvSIG: 10 créditos.

* “Extensión de Análisis de Redes de gvSIG en Español”. Duración: 2 semanas. Programa de certificaciones gvSIG: 20 Créditos.

* “Extensión de publicación de servicios OGC de gvSIG en español”. Duración: 1 semana. Programa de certificaciones gvSIG: 20 créditos.

* “PostGIS Básico para usuarios en Español”. Duración: 3 semanas.Programa de certificaciones IDE: 40 créditos.

Al participar en cualquiera de estos cursos obtienes créditos del programa de certificación gvSIG que te permite optar a la certificación “gvSIG Usuario” y “gvSIG Usuario Experto” [1]; al mismo tiempo que contribuyes al sostenimiento del proyecto gvSIG.

Para mayor información visita nuestra plataforma www.gvsig-training.com o escríbenos a las siguientes direcciones de correo electrónico:
inscripciones@gvsig-training.com; info@gvsig-training.com

[1] http://www.gvsig.com/servicios/certificacion/certificacion

Posted in Business, Italian, spanish, training | Tagged , | Leave a comment

gvSIG Batoví, se presenta la primera distribución de gvSIG para Educación (gvSIG Educa)

El Ministro de Transporte y Obras Públicas (MTOP) de la República Oriental del Uruguay, Enrique Pintado, presentó el pasado jueves gvSIG Batoví, primera distribución uruguaya que da origen a gvSIG Educa.

gvSIG Educa es una personalización del Sistema de Información Geográfica libre gvSIG Desktop, adaptado como herramienta para la educación de materias con componente geográfica. gvSIG Educa tiene como objetivo servir de herramienta a educadores para facilitar a los alumnos el análisis y la comprensión del territorio, teniendo la posibilidad de adaptarse a los distintos niveles o sistemas educativos. gvSIG Educa facilita el aprendizaje por la interactividad de los alumnos con la información, añadiendo la componente espacial al estudio de las materias, y facilitando la asimilación de conceptos mediante herramientas tan visuales como los mapas temáticos o que ayudan a comprender las relaciones espaciales.

gvSIG Batoví es, de este modo, la puesta en marcha de un software libre que probablemente sea adaptado y utilizado en un gran número de países. gvSIG Batoví es un software impulsado por la Dirección Nacional de Topografía (MTOP) para el Plan Ceibal, por el cual los estudiantes de Primaria y Secundaria tendrán acceso a nutrida información de carácter didáctico y representada mediante mapas.

“Desde la implementación del Plan Ceibal, el gobierno busca incentivar políticas que favorezcan al desarrollo y beneficio de la educación de los niños, nuestro futuro y presente del país”, destacó Pintado, precisando que por sus características geográficas nuestro país no puede producir bienes a gran escala, “pero sí podemos generar conocimiento sin límite de ninguna especie”.

Durante la presentación de esta nueva herramienta, ceremonia de la que participaron el Subsecretario de la cartera, Ing. Pablo Genta, el Director Nacional de Topografía (MTOP), Ing. Jorge Franco y el Decano de la Facultad de Ingeniería (UDELAR), Ing. Héctor Cancela, el Ministro señaló que más allá de esas limitantes productivas, “los uruguayos podemos distinguirnos por la inteligencia, por la capacidad de innovar e investigar, y vincular esos conocimiento al desarrollo”. “Y para ello, este nuevo software llamado “gvSIG Batoví”, resultará fundamental ya que permite a los gurises (como se denomina a los niños en Uruguay) acceder a un vasto universo de conocimientos”, acotó.

El programa “gvSIG Batoví”, producto del trabajo conjunto de la Dirección Nacional de Topografía, la Facultad de Ingeniería y la Asociación gvSIG, posibilitará a los estudiantes adquirir conocimientos de Geografía a través de la utilización de las XO -computadora portátil de bajo coste-, extensible también a otras áreas del conocimiento, como Historia, Biología, entre otros.

Lo más interesante es la posibilidad que le brinda al docente y/o estudiante de elaborar su propio mapa temático a partir de las distintas capas de información que disponga del territorio. Con ello se busca fomentar el aprendizaje por descubrimiento, convirtiendo al trabajo cartográfico en un saber formativo.

Con “gvSIG Batoví” se presenta un primer conjunto de mapas temáticos previamente elaborados del territorio uruguayo, como por ejemplo mapas políticos y físicos, distribución de la población, infraestructura del transporte y la comunicación, y cobertura del suelo. La facilidad de acceso a estos mapas temáticos -como plugins instalables desde la propia aplicación- permitirá compartir con facilidad cartografía entre docentes y estudiantes de toda la comunidad de usuarios de este software.

Más allá del ámbito educativo, los usuarios profesionales de la tecnología gvSIG, podrán acceder en forma de plugins a estas nuevas funcionalidades de crear y compartir mapas, convirtiéndose así en una nueva forma, extremamente sencilla, de compartir información territorial.

Cabe destacar que en las Cuartas Jornadas de Latinoamérica y Caribe de gvSIG y Segundas Jornadas Uruguayas de gvSIG se incluirá una presentación y un taller sobre el gvSIG Batoví.

Para concluir es de destacar el énfasis en lo colectivo que tuvo este proyecto, ya que incluyó la participación coordinada de 4 instituciones: Dirección Nacional de Topografía del MTOP (Uruguay) como propulsora de la idea; Asociación gvSIG (España) como principal desarrolladora de la herramienta y demás aspectos del proyecto (documentación, difusión, etc.); Grupo en Tecnologías de la Información Geoespacial de la Fac. de Ingeniería (UDELAR – Uruguay) como contraparte local del desarrollo; y el Centro Ceibal como responsable de la distribución e implementación del producto en el Plan Ceibal (Ceibal significa “Conectividad Educativa de Infomática Básica para el Aprendizaje en Línea”, además de aludir a la flor nacional, el ceibo).

Posted in community, gvSIG Desktop, spanish | Tagged , , | Leave a comment

gvSIG 1.11 se une al portfolio de software de Munich

He considerado interesante traducir esta importante noticia que nos llega desde el Ayuntamiento de la ciudad de Munich, de la mano de Georg Sedlmeir.

Saludos
Valenty


Luego de varios años de preparativos y pruebas, el Departamento de Salud y Medio Ambiente del Ayuntamiento de Munich se complace en informar que gvSIG 1.11 ya se ha incorporado al Portafolio de Software Estándar de la Ciudad de Munich, lo que significa que todos los usuarios en la administración de la ciudad que necesiten gvSIG en su escritorio pueden tenerlo asignado mediante un procedimiento de instalación automática, listo para usar!

Esto también significa que gvSIG finalmente deja los confines del Departamento de Salud y Medio Ambiente y da un paso más en el proceso de establecerse como la herramienta de Código Abierto compatible con OGC y como alternativa al software propietario para toda la municipalidad.

Con el fin de apoyar aún más este proceso y difundir esta noticia, ha sido desarrollado un curso de formación interna en la organización, con una duración de 2 días, dirigido a un público que ya está familiarizado con los conceptos de SIG, para probar el estado del arte de gvSIG como aplicación de Código Abierto. Un primer curso se llevará a cabo este otoño, con otros más por venir el próximo año.

Posted in gvSIG Desktop, spanish | Leave a comment

gvSIG 1.11 now official part of the standard software portfolio in the City of Munich!

After several years of preparations and testing, the Department of Health and Environment of the City of Munich is happy to report that gvSIG 1.11 has now been incorporated into the City of Munich’s standard software portfolio, which means that everyone in the city administration who needs gvSIG on their desktop

can have it assigned with an automatic installation procedure and is ready to go! This also means that gvSIG has finally left the confines of the Department of Health and Environment and is taking another step in the process of establishing it as an OGC compliant, Open Source alternative to proprietary software throughout the municipality.

In order to support this process further and spread the news, an internal 2-day training course has been developed, targeted at an audience already familiar with GIS concepts and ready to try out a state of the art open source GIS application. A first course will take place this fall, with more to come early next year.

 

Posted in english, gvSIG Desktop | 1 Comment

Hilos y gvSIG (4 de 4): Interactuando con el usuario

En el articulo anterior “Hilos y gvSIG: Estructura de nuestro proceso (3 de 4)” vimos cómo podíamos estructurar la lógica de nuestro proceso. En este ultimo articulo vamos a ver cómo podríamos hacer para interactuar con la interface gráfica desde él.

Cuando estamos trabajando en java con swing y múltiples hilos de ejecución tenemos que tener algo de cuidado al interactuar con el interface de usuario. En una aplicación swing el acceso a los elementos gráficos debe realizarse desde el hilo que controla el manejador de eventos de swing. Si desde otro hilo intentamos acceder a los elementos graficos podemos tener resultados inesperados. La librería de swing aporta varias funciones de utilidad para poder sincronizar nuestras operaciones con las que swing hace en su hilo de ejecución. Nos vamos a quedar con tres de ellas:

  • SwingUtilities.isEventDispatchThread, que nos dice si ya estamos ejecutándonos en el hilo de swing
  • SwingUtilities.invokeLater(Runnable action) que se encarga de encolar la ejecución de “action” en el hilo de swing para que se ejecute cuando este pueda.
  • SwingUtilities.invokeAndWait(Runnable action) que se encarga de encolar la petición en el hilo de swing y esperar a que esta se ejecute.

Usando estos tres métodos podemos asegurarnos que las partes de código que tienen que ver con el GUI se ejecuten en el hilo del manejador de eventos de swing.

Por ejemplo, si quisiésemos mostrar un cuadro de diálogo del estilo de showMessageDialog podríamos hacer algo como:

if (!SwingUtilities.isEventDispatchThread()) {
  try {

    SwingUtilities.invokeAndWait(new Runnable() {
      public void run() {

        JOptionPane.showMessageDialog(null, "Éste sería el mensaje a mostrar");
      }
    });

  } catch (InterruptedException e) {
    logger.info("Can't show message dialog ", e);

  } catch (InvocationTargetException e) {
    logger.info("Can't show message dialog ", e);

  }
} else {
  JOptionPane.showMessageDialog(null, "Éste sería el mensaje a mostrar");

}

Aunque de esta manera podemos asegurarnos que nuestros mensajes se presentan al usuario de forma correcta aunque estemos en un hilo distinto al del manejador de eventos de swing, suele resultar bastante engorroso, por eso disponemos de algúnas funciones en gvSIG para acceder a algunos de los diálogos standard. Los siguientes métodos de gvSIG nos permiten presentar algunos de los cuadros de diálogo de la clase JOptionPane sin preocuparnos de esto:

  • ApplicationManager.messageDialog nos muestra un mensaje similar a JOptionPane.showMessageDialog
  • ApplicationManager.confirmDialog nos muestra un mensaje similar a JOptionPane.showConfirmDialog
  • ApplicationManager.inputDialog nos muestra un mensaje similar a JOptionPane.showInputDialog

Además de estos métodos disponemos de un método ApplicationManager.message que nos permitirá presentar un mensaje en la barra de estado de gvSIG, y que también realiza las comprobaciones adecuadas para asegurarse que funciona aunque no estemos en el hilo de swing.

Con estos cuatro métodos junto con el mecanismo del TaskStatus podemos dotar a nuestros procesos de algo de interacción con el usuario sin necesidad de encargarnos nosotros mismos de sincronizarnos con el hilo de swing. Si precisamos una interacción más rica, por ejemplo presentar nuestros propios cuadros de diálogo desde nuestro hilo de ejecución, disponemos de dos métodos más en el ApplicationManager:

  • createComponent, que pasándole la clase que implementa un componente de AWT se encarga de crearlo en el hilo de swing.
  • Y showDialog(final Component contents, final String title), que recibe nuestro JPanel, normalmente instanciado con createComponent y se encarga de mostrarlo a modo de diálogo modal respecto a nuestro hilo.

Y por último comentar que se está realizando un esfuerzo para que la gran mayoría de los métodos del API de andami y el plugin de gvSIG se comporten de forma segura respecto a su ejecución desde otros hilos distintos al del controlador de eventos de swing.

Bueno… con estas utilidades en nuestra caja de herramientas volvamos a nuestra clase MyProcess. En el articulo anterior habíamos visto cómo podría ser la estructura de nuestra clase que implementase nuestro proceso. Habíamos visto también ya que en algún momento se presentaba un cuadro de diálogo al usuario para informar de algún error, pero no nos habíamos centrado en ello.

Así por ejemplo, al final de nuestro bucle en el método run teníamos algo como:

...
  this.postPrecess();
  if (status.isCancellationRequested()) {

    status.cancel();
    return;
  }
  application.message("Process terminated", JOptionPane.INFORMATION_MESSAGE);

} catch (Exception e) {
  logger.info("Error in process", e);

  if (status != null) {
    status.abort();

  }
  application.message("Process error", JOptionPane.WARNING_MESSAGE);
  application.messageDialog(

          "Se ha producido un error realizando el proceso y éste terminará de forma inesperada.\n\n"
              + e.getMessage(), this.getName(),
          JOptionPane.WARNING_MESSAGE);

} finally {

...

En donde podemos ver cómo se invoca a un par de métodos que interactúan con el usuario. Por un lado tenemos la llamada:

application.message("Process terminated", JOptionPane.INFORMATION_MESSAGE);

Que se encarga de mostrar en la barra de estado de gvSIG un mensaje informándonos que ha terminado la ejecución de nuestro proceso. Nótese que como estamos usando el método message del ApplicationManager no es preciso sincronizar su ejecución con el hilo de swing, como hemos comentado antes.

Y un poco más abajo, cuando se atrapan los errores, se muestra un diálogo al usuario informando de ello:

application.messageDialog(
        "Se ha producido un error realizando el proceso y éste terminará de forma inesperada.\n\n"

            + e.getMessage(), this.getName(),
        JOptionPane.WARNING_MESSAGE);

Con todo esto, vamos a ver qué podía hacer nuestro proceso, más para ilustrar el uso de estas funciones que para hacer algo real. Así nuestro proceso se limitará ha hacer un sleep a cada iteración, y además:

  1. Cuando lleve recorridos el 10% de los elementos presentará un mensaje de tipo informativo en la barra de estado informando de ello, además de mostrarlo en el indicador de progreso usando el taskstatus:
    status.message("10%");
    
    application.message("this is the row " + i,
        JOptionPane.INFORMATION_MESSAGE);
  2. Cuando lleve recorridos el 20% de los elementos presentará un mensaje de tipo advertencia en la barra de estado informando de ello, además de mostrarlo en el indicador de progreso usando el taskstatus:
    status.message("20%");
    application.message("this is the row " + i,
    
        JOptionPane.WARNING_MESSAGE);
  3. Cuando lleve recorridos el 30% de los elementos presentara un mensaje de tipo error en la barra de estado informando de ello, además de mostrarlo en el indicador de progreso usando el taskstatus:
    status.message("30%");
    
    application.message("this is the row " + i,
        JOptionPane.ERROR_MESSAGE);
  4. Cuando lleve el 40% presentara un mensaje del tipo ShowMessageDialoginformando de ello:
    status.message("40%");
    application.messageDialog("Just procesing "+i+" items",
    
        this.getName(), JOptionPane.INFORMATION_MESSAGE);

    Aquí el proceso se interrumpirá hasta que el usuario pulse en el botón aceptar, tras lo cual continuara con su ejecución.

  5. Cuando lleve el 50% informará de ello al usuario, y preguntará si éste desea interrumpir nuestro proceso:
    status.message("50%");
    int confirm = application
        .confirmDialog("Quiere cancelar el procesp?",
    
            this.getName(), JOptionPane.YES_NO_OPTION,
            JOptionPane.QUESTION_MESSAGE);
    
    if (confirm == JOptionPane.YES_OPTION) {
      status.cancelRequest();
    
    }

    En caso de que el usuario responda que si quiere cancelar la ejecución, llamamos al método cancelRequest y ya lo procesaremos a la siguiente entrada en nuestro bucle.

  6. Por ultimo, cuando el proceso lleve el 60%, pediremos al usuario que entre una cadena, que luego mostraremos en la barra de estado:
    status.message("60%");
    
    String value = application.inputDialog("Introduce un valor",this.getName());
    if (value != null) {
    
      application.message("Entered: " + value,
          JOptionPane.INFORMATION_MESSAGE);
    
    } else {
      application.message("Input cancelled",
          JOptionPane.INFORMATION_MESSAGE);
    
    }

Pongamos todo esto junto y veamos como nos quedaría nuestro método processItem:

private void processItem(int i) throws InterruptedException {

  ApplicationManager application = ApplicationLocator.getManager();
  SimpleTaskStatus status = (SimpleTaskStatus) this.getTaskStatus();

  switch ((100 * i) / this.maxValue) {

  case 10:
    status.message("10%");
    application.message("this is the row " + i,

        JOptionPane.INFORMATION_MESSAGE);
    break;
  case 20:
    status.message("20%");

    application.message("this is the row " + i,
        JOptionPane.WARNING_MESSAGE);

    break;
  case 30:
    status.message("30%");

    application.message("this is the row " + i,
        JOptionPane.ERROR_MESSAGE);

    break;
  case 40:
    status.message("40%");

    application.messageDialog("Just procesing "+i+" items",
        this.getName(), JOptionPane.INFORMATION_MESSAGE);

    break;
  case 50:
    status.message("50%");

    int confirm = application
        .confirmDialog("Quiere cancelar el procesp?",
            this.getName(), JOptionPane.YES_NO_OPTION,

            JOptionPane.QUESTION_MESSAGE);
    if (confirm == JOptionPane.YES_OPTION) {

      status.cancelRequest();
    }
    break;
  case 60:

    status.message("60%");
    String value = application.inputDialog("Introduce un valor",this.getName());

    if (value != null) {
      application.message("Entered: " + value,

          JOptionPane.INFORMATION_MESSAGE);
    } else {
      application.message("Input cancelled",

          JOptionPane.INFORMATION_MESSAGE);
    }
    break;
  }
  Thread.sleep(this.sleepTime);

}

No se trata de un código real, solo sirve para ilustrar el uso de las funciones más simples a nuestra disposición para interactuar con el usuario. Soy consciente que el control de los porcentajes puede provocar que se muestre algún diálogo más de una vez, pero prefiero no complicar el control de eso y dejar el código de la forma más simple, ya que lo importante creo que es ilustrar cómo podemos invocar a nuestros diálogos de forma simple.

Veamos ahora como podríamos añadir a nuestro proceso algún cuadro de diálogo personalizado. Supongamos que al iniciar nuestro proceso deseamos presentar al usuario un cuadro de diálogo preguntando algunos datos, y por la razón que sea ya no nos encontramos en el hilo del controlador de eventos de swing. Supondremos que tenemos una clase MyDialog que implementa un panel de swing, JPanel, y queremos mostrarla y esperar a que el usuario introduzca algún dato para que pueda continuar nuestro proceso. Nuestro panel MyDialog, espera recibir en su constructor una instancia de MyProcess, para acceder a los parámetros que éste tiene y poder mostrarlos al usuario y luego recuperarlos.

Lo primero que haremos sera añadir a nuestro MyProcess unos setters y getters para acceder a las propiedades privadas que nos interese:

public int getMaxValue() {
  return maxValue;
}

public void setMaxValue(int maxValue) {
  this.maxValue = maxValue;

}
public long getSleepTime() {
  return sleepTime;

}
public void setSleepTime(long sleepTime) {
  this.sleepTime = sleepTime;

}

Luego para mostrar nuestro diálogo, primero crearemos nuestro panel:

Component panel = application.createComponent(MyDialog.class, this);

Notar que no hemos creado el panel directamente invocando a:

Component panel = new MyDialog(this);

Ya que es podría provocar algún efecto extraño al no estar en el hilo de swing. LLamando a createComponent nos aseguramos que la creación de nuestro componente se hará en el hilo de swing, y que nuestro hilo esperara a que éste sea creado y nos lo devolverá.

Y luego para mostrar un cuadro de diálogo con ese panel llamaremos a:

application.showDialog(panel, this.getName());

Que se encargará de presentar una ventana de gvSIG con el panel indicado, y con el título que le hayamos dicho, en este caso el nombre de nuestro hilo, y esperará a que ésta sea cerrada para devolver el control a nuestro hilo.

Todo esto junto en el método preProcess quedaría:

private void preProcess() {
  SimpleTaskStatus status = (SimpleTaskStatus) this.getTaskStatus();

  status.setTitle("Getting parameters");
  Component panel = application.createComponent(MyDialog.class, this);

  application.showDialog(panel, this.getName());
}

En cuanto al método postProcess que hemos comentado en el articulo anterior, en nuestro caso quedaría vacío:

private void postPrecess() {
  // In this example do nothing
}

Con esto más o menos quedan cubiertas las principales acciones que podemos querer hacer desde nuestro hilo y qué funciones aporta gvSIG para ayudarnos en ello.

Respecto a nuestra clase MyDialog podría ser algo como:

public class MyDialog extends MyDialogLayout {
  private static final long serialVersionUID = 1919826881234125305L;

  private MyProcess process = null;

  public MyDialog(MyProcess process) {

    super();
    this.process = process;
    this.inputSleepTime.setValue(this.process.getSleepTime());

    this.inputMaxIterations.setValue(this.process.getMaxValue());
    this.buttonAcept.addActionListener(new ActionListener() {

      public void actionPerformed(ActionEvent arg0) {
        doAcept();
      }

    });
    this.buttonCancel.addActionListener(new ActionListener() {

      public void actionPerformed(ActionEvent arg0) {
        doCancel();
      }

    });
  }
  private void doAcept() {
    this.process.setSleepTime(((SpinnerNumberModel) inputSleepTime.getModel()).getNumber().intValue());

    this.process.setMaxValue(((SpinnerNumberModel) inputMaxIterations.getModel()).getNumber().intValue());

    this.closeWindow();
  }
  private void doCancel() {

    this.process.cancelRequest();
    this.closeWindow();
  }

  private void closeWindow() {
    this.setVisible(false);

  }
}

Lo más importante es el método closeWindow. El método showDialog del ApplicationManager espera a que el componente pasado sea ocultado para interpretar que se quiere cerrar la ventana, así que desde nuestro panel, lo único que hacemos es poner visible a false para indicar que queremos cerrar la ventana. Al respecto de MyDialog comentar que suelo separar la creación del GUI de la lógica de éste, así que la clase MyDialog extiende a MyDialogLayout que contiene la creación y posicionamiento de todo los controles, que son usados desde MyDialog. No creo que tenga gran misterio la creación y posicionamiento de los controles, así que no la voy a incluir en este articulo.

Como nota final, me gustaría hacer hincapié en un idea. Aunque aquí haya comentado cómo podemos hacer para desde nuestro proceso interactuar con el usuario, es una mala política hacerlo. No recomiendo hacerlo más allá de interactuar con el componente TaskStatus para ir informando del progreso de nuestro proceso. Solo en caso de que sea necesario hacerlo deberíamos interactuar con el GUI desde un proceso que se espera que esté haciendo algún tipo de tarea en segundo plano.

Espero que haya servido para ilustrar cómo estructurar este tipo de tareas en gvSIG, y qué recursos tenemos a nuestro alcance para facilitarnos hacerlas.

Un saludo

Joaquin

Posted in development, gvSIG Desktop, spanish | Tagged | 1 Comment

Hilos y gvSIG (3 de 4): Estructura de nuestro proceso

En el articulo anterior, “Hilos y gvSIG (2 de 4): TaskStatus“, vimos las funcionalidades relacionadas con la utilidad TaskStatus, ahora vamos a ver cómo podríamos hacer para crear un proceso y ejecutarlo como un hilo de ejecución independiente de gvSIG que nos permita dejar al usuario seguir interactuando con el resto de la aplicación mientras éste se esta ejecutando. Para eso crearemos dos clases, MyExtension, que será una extensión de gvSIG encargada de lanzar el proceso y MyProcess, que estará implementado mediante un hilo de java.

En lo que respecta a nuestra extensión tendremos que tener encuenta algunas cosas:

  • Cada vez que el usuario lo solicite lanzará la ejecución de nuestro proceso en un hilo aparte.
  • Si se intenta ejecutar y el proceso ya está en ejecución presentará un mensaje al usuario indicando que en estos momentos ya está en ejecución nuestro proceso indicando que no podrá ejecutarlo hasta que éste termine.
  • La herramienta estará visible siempre, pero solo estará activa si no está nuestro proceso en ejecución.

Para esto nuestra extensión guardará una referencia a nuestro proceso, y en el método isEnabled comprobará si tenemos una instancia de nuestro proceso y si esta está viva a través del método isAlive de la clase Thread. Así mismo, en el execute se realizará una comprobación similar antes de lanzar la ejecución del proceso.

Veamos cómo seria el código de nuestra extensión:

public class MyExtension extends Extension {

  @SuppressWarnings("unused")
  private static Logger logger = LoggerFactory.getLogger(MyExtension.class);

  private MyProcess process = null;

  public void initialize() {

    // Do nothing
  }
  public void execute(String actionCommand) {

    if ("tools-devel-my-process".equalsIgnoreCase(actionCommand)) {
      if (process != null && process.isAlive()) {

        ApplicationManager application = ApplicationLocator.getManager();
        application.messageDialog(
            "Process already running. Wait to terminate.",

            "Test task", JOptionPane.WARNING_MESSAGE);
        return;
      }
      process = new MyProcess();

      process.start();
    }
  }
  public boolean isEnabled() {

    if (process != null && process.isAlive()) { 
      return false;

    }
    return true;
  }
  public boolean isVisible() {

    return true;
  }
}

Una vez ya tenemos preparada nuestra extensión veamos qué tendríamos en nuestra clase MyProcess. De forma general, asumiremos que nuestro proceso tendrá una serie de tareas previas, un bloque de tareas constituido por un bucle en el que a cada pasada se van ejecutando nuestro proceso y una serie de tareas a ejecutar a la finalización de éste. Así mismo, para el caso de ejemplo, voy a suponer que sé el número de iteraciones que va a hacer el proceso, lo que me permitirá informar a través del TaskStatus del avance del proceso. Tendremos definidos los siguientes métodos:

  • run, se tratará del hilo principal de ejecución. Contendrá el código principal de nuestro proceso haciendo las veces de main de éste.
  • preProcess, el método en el que englobaremos las tareas previas al bloque principales de nuestro proceso.
  • processItem, que será el encargado de procesar cada uno de los ítems de nuestro proceso.
  • postProcess, que realizará las tareas de finalización de nuestro proceso.

Los pasos a hacer en el método run serian:

  1. realización de la tareas previas:

    this.preProcess();
  2. Comprobar si se ha solicitado la cancelación del proceso:

    if (status.isCancellationRequested()) {
      status.cancel();
      return;
    
    }
  3. inicializar el status con el número de iteraciones que va a tener nuestro proceso:

    status.setRangeOfValues(1, this.maxValue);
  4. Iterar, comprobando al comienzo de cada iteración si se ha solicitado la cancelación
    del proceso y estableciendo el estado de progreso:

    for (int i = 1; i < this.maxValue; i++) {
    
      // Si ha sido solicitada la cancelacion de la tarea
      // la marcamos como cancelada y salimos del proceso.
      if (status.isCancellationRequested()) {
    
        status.cancel();
        return;
      }
      // Informamos del progreso de la tarea
      status.setCurValue(i);

    A cada iteración realizaremos las tareas propias de nuestro proceso:

    this.processItem(i);
  5. Realizar las tareas de post-proceso:

    this.postPrecess();
  6. Comprobar si se ha solicitado la cancelación durante la ejecución de las tareas
    de post-proceso:

    if (status.isCancellationRequested()) {
      status.cancel();
    
      return;
    }
  7. A la terminación de nuestro proceso marcar el status como terminado.
    Normalmente esto lo haremos en la instrucción finally, para asegurarnos
    que a la salida de nuestro proceso siempre se actualiza el estado de
    éste:

    } finally {
    
      if (status != null) {
        // Mark process as terminate if it is running.
        if (status.isRunning()) {
    
          status.terminate();
        }
      }
    }

Es importante tener en cuenta algunas consideraciones:

  • Deberemos consultar si se ha pedido la cancelación de nuestro proceso, a cada iteración de éste, o si se trata de un proceso muy pesado, con un alto número de iteraciones, cada cierto número de éstas que sea razonable en tiempo de usuario.
  • Deberemos atrapar los errores de forma adecuada. Hay que tener en cuenta que si éstos se producen no se propagarán hasta el interface de usuario de la aplicación, y el usuario puede no enterarse de problemas durante la ejecución de nuestro proceso.
  • Deberemos marcar nuestro proceso como terminado a su finalización, lo que normalmente haremos con la clausula finally
  • No podremos interactuar con el interface de usuario directamente. Swing no está preparado para trabajar en multihilo, así que solo podremos hacerlo a través de métodos que estén preparados para ello o utilizando los métodos invokeLater e invokeAndWait de la clase SwingUtilities de swing tal como vimos en el ejemplo de la clase MyObserver.

Con todas estas consideraciones en mente veamos como podría quedar nuestra clase MyProcess :

public class MyProcess  extends AbstractMonitorableTask {

  private static Logger logger = LoggerFactory.getLogger(MyProcess.class);

  private ApplicationManager application = null;
  private int maxValue = 100;

  private long sleepTime = 100;

  protected MyProcess() {

    super("MyProcess");
    this.application = ApplicationLocator.getManager();

  }
  public void run() {
    SimpleTaskStatus status = null;

    try {
      status = (SimpleTaskStatus) this.getTaskStatus();

      this.preProcess();
      if (status.isCancellationRequested()) {

        status.cancel();
        return;
      }
      status.setRangeOfValues(1, this.maxValue);

      for (int i = 1; i < this.maxValue; i++) {

        // Si ha sido solicitada la cancelacion de la tarea
        // la marcamos como cancelada y salimos del proceso.
        if (status.isCancellationRequested()) {

          status.cancel();
          return;
        }
        // Informamos del progreso de la tarea
        status.setCurValue(i);

        this.processItem(i);
      }
      this.postPrecess();

      if (status.isCancellationRequested()) {
        status.cancel();

        return;
      }
      application.message("Process terminated", JOptionPane.INFORMATION_MESSAGE);

    } catch (Exception e) {
      logger.info("Error in process", e);

      if (status != null) {
        status.abort();

      }
      application.message("Process error", JOptionPane.WARNING_MESSAGE);
      application.messageDialog(

              "Se ha producido un error realizando el proceso y este terminara de forma inesperada.\n\n"
                  + e.getMessage(), this.getName(),
              JOptionPane.WARNING_MESSAGE);

    } finally {
      if (status != null) {

        // Mark process as terminate if it is running.
        if (status.isRunning()) {
          status.terminate();

        }
      }
    }
  }
  private void preProcess() {

    ...
  }
  private void processItem(int i) throws InterruptedException {

    ...
  }
  private void postPrecess() {
    ...

  }
}

Tal como se han descrito las clases MyExtension y MyProcess, éstas podrían quedar como un esquema general a la hora de implementar procesos en gvSIG. Las adaptaríamos a nuestras necesidades y las podríamos utilizar de cara a construir nuestros procesos de forma que no fuesen bloqueantes respecto al interface de gvSIG.

En el próximo articulo, “Hilos y gvSIG (4 de 4): Interactuando con el usuario“, vamos a seguir viendo cómo podemos abordar algunas cosas más relacionadas con el manejo de hilos, y veremos en un ejemplo sencillo qué podemos tener en los metodos preProcess y processItem, y cómo podríamos hacer para interactuar desde ellos con el interfaz de usuario en caso de que lo necesitásemos.

Un saludo

Joaquin

Posted in development, gvSIG Desktop, spanish | Tagged | 2 Comments

Hilos y gvSIG (2 de 4): TaskStatus

En el articulo anterior, “Hilos y gvSIG (1 de 4)“, vimos una introducción a lo que podían ser la herramientas que nos ofrece gvSIG para crear nuestros propios procesos sin que estos bloqueen la interface de usuario de gvSIG.
Vamos a continuar con ello viendo las utilidades relacionadas con el TaskStatus.

Para gestionar el estado y progreso de tareas o procesos en gvSIG disponemos del mecanismo de TaskStatus, que se encuentra implementado en la librería de org.gvsig.tools. Las principales entidades relacionadas con este mecanismo que nos encontraremos serán:

  • TaskStatus. Que representa el estado en el que se encuentra un proceso o tarea. Tiene métodos para consultar el estado en que se encuentra la tarea, pero no para establecerlo. Este interface es el que deben usar los procesos que quieren consultar el estado de otros procesos.
  • TaskStatusManager. Hace de factoría para la creación de TaskStatus, así como mantiene un registro de éstos para poder consultar el estado de las tareas que se encuentren en ejecución.
  • SimpleTaskStatus. Extiende el interface TaskStatus con métodos que nos permiten actualizar el estado de la tarea. Es usado por la propia tarea o proceso para mantener actualizado la información de su estado.
  • AbstractMonitorableTask. Se trata de una clase abstracta que extiende a la clase Thread, añadiéndole métodos para obtener el TaskStatus asociado a éste. Normalmente cuando creemos nuestros procesos extenderemos de esta clase en lugar de la clase Thread.

El TaskStatus, nos da información sobre el estado del proceso, nos informa de características del proceso como:

  • Si se puede determinar la duración del proceso. Es decir si es posible calcular qué llevamos y cuánto falta (isIndeterminate).
  • Si el proceso es cancelable o no (isCancelable).
  • Un titulo identificativo del proceso (getTitle)

También nos permite consultar el progreso de nuestro proceso:

  • Consultar el porcentaje de avance de éste (getCompleted)
  • O una etiqueta que identifique qué esta haciendo en un momento dado (getLabel).

Nos permite solicitar la cancelación del proceso (cancelRequest). No nos permite cancelarlo, esto es algo que el propio proceso debe decidir, desde fuera lo único que podemos hacer es pedir que cancele su ejecución.

Y por último consultar su estado:

  • isRunning, el proceso está en ejecución.
  • isRequestCanceled, el proceso está en ejecución y se ha solicitado su cancelación.
  • isAborted, el proceso ha abortado su ejecución, normalmente debido a algún error durante la ejecución de éste.
  • isCancelled, el proceso se ha cancelado por petición externa a éste, normalmente por la intervención del usuario o de algún otro proceso invocando al método cancelRequest.

El TaskStatusManager, nos permite crear instancias de TaskStatus mediante el método createDefaultSimpleTaskStatus, y añadir, consultar, o eliminar un TaskStatus de la lista de status que mantiene.

Tanto el TaskStatus, como el TaskStatusManager son observables, y permiten registrar observadores para poder seguir el estado de una tarea. Así si quisiésemos presentar información de las tareas que hay en ejecución en un momento dado solo tendríamos que registrarnos como observadores del taskStatusManager. Si lo hiciésemos tendríamos que tener la precaución de asegurarnos en el método update de nuestro observador que estamos en el hilo de ejecución de swing antes de presentar la información en el interface gráfico. Podría ser algo como:

class MyObserver implements Observer {
  public void update(final Observable observable,final Object notification) {

    if (!SwingUtilities.isEventDispatchThread()) {
      SwingUtilities.invokeLater(new Runnable() {

        public void run() {
          update(observable,notification);

        }
      });
      return;
    }
    ...
    Procesar notificacion
    ...

  }
}

Si estamos observando al TaskStatusManager recibiremos como observable a éste y como notification el TaskStatus involucrado o null. Por ejemplo, añadir un taskstatus al manager o modificar un taskstatus registrado en el manager provocará que nos llegue como notification el taskstaus añadido o modificado y cuando se elimine uno nos llegara el que queremos eliminar o null.

El otro interface importante relacionado con TaskStatus es el SimpleTaskStatus. Se trata del interface que usará un proceso o tarea para mantener actualizado su estado. Añade los siguientes métodos al TaskStatus:

  • add y remove, que provocaran que el TaskStatus se registre o elimine en el manager para poder estar en la lista de tareas disponibles de forma publica.
  • setAutoremove y getAutoremove, que nos permitirán consultar y fijar la propiedad autoremove, que indica si el TaskStatus deberá ser eliminado del manager al terminar su ejecución de forma automática o no.
  • setCancelable para indicar si nuestro proceso es cancelable o no.
  • terminate para indicar que nuestro proceso ha terminado su ejecución y además lo ha hecho de forma correcta.
  • cancel para indicar que nuestro proceso ha terminado su ejecución debido a una petición de cancelación.
  • abort para indicar que nuestro proceso ha terminado su ejecución debido a una condición de error.
  • setRangeOfValues y setCurValue para que indiquemos, si procede, cuál va a ser la duración del proceso y en qué estado se encuentra. Estos valores serán usados para calcular el getCompleted y el isIndeterminate.
  • setTitle y message para ofrecer una información textual del avance del proceso.

Normalmente no crearemos directamente un TaskStatus, sino que para crear nuestro propio proceso extenderemos de la clase AbstractMonitorableTask. Esta instanciará y registrará en el manager una instancia de TaskStatus, añadiendo los métodos:

  • cancelRequest, que nos permitirá solicitar la cancelación de nuestro hilo.
  • getTaskStatus, que nos permitirá obtener el TaskStatus asociado al hilo.

Con todas estas piezas a nuestra disposición vamos a ver cómo podríamos hacer una pequeña extensión para gvSIG que lance un proceso en un hilo aparte, y cómo habría que hacer en este hilo para ir informando del progreso de su ejecución a gvSIG y que éste pueda mostrar esa información.

Crearemos tres clases:

  • MyExtension, que será la encargada de lanzar nuestro proceso, controlando que no se pueda volver a lanzar mientras no haya terminado la ejecución de éste.
  • MyProcess, que extenderá a AbstractMonitorableTask, y tendrá el código de nuestro proceso.
  • MyDialog, que representara un pequeño cuadro de dialogo con algunas propiedades que puede requerir nuestro proceso.

En el próximo articulo,”Hilos y gvSIG (3 de 4): Estructura de nuestro proceso“,  continuaremos viendo cómo estructurar nuestra extensión y nuestro proceso.

Un saludo

Joaquin

Posted in development, gvSIG Desktop, spanish | Tagged | 2 Comments

Hilos y gvSIG (1 de 4)

En muchas ocasiones tenemos que implementar algún proceso en gvSIG que requiere cierto tiempo, y al ejecutarlo deja bloqueada la interface de usuario. Este tipo de procesos son candidatos ideales para ejecutarlos en un hilo separado permitiendo así que el usuario pueda interactuar con otras partes de gvSIG mientras éste se esta ejecutando. Sin embargo muchas veces no lo hacemos por que esto conlleva cierta complicación añadida. Intentar acceder al interface de usuario desde un hilo que no sea el hilo principal de gvSIG puede causar efectos inesperados en ella o incluso provocar que ésta quede bloqueada. Algo tan simple como actualizar una barra de progreso o presentar un mensaje al usuario desde el hilo de nuestro proceso puede convertirse en una pesadilla.

Ahora bien, en gvSIG 2 se han introducido algunas herramientas que nos pueden facilitar estas cosas. No es que nos vayan a quitar todo el trabajo o que podamos desentendernos de los problemas inherentes a trabajar con swing y múltiples hilos de ejecución, pero si ayudarnos con algunas cosas.

Las principales dificultades que nos solemos encontrar cuando intentamos ejecutar un proceso en un hilo separado de ejecución giran alrededor de:

  • Presentar al usuario un indicador del progreso de nuestro proceso.
  • Dar opción al usuario a poder cancelar la ejecución del proceso.
  • Poder presentar al usuario información o requerir de él información a lo largo de la ejecución del proceso. Por ejemplo durante la ejecución del proceso se produce alguna condición de error y queremos preguntar al usuario para poder continuar y no abortar la ejecución de éste.

En relación a estas tareas podemos encontrar algunas herramientas en gvSIG para ayudarnos con ellas. En la librería org.gvsig.tools nos encontraremos con:

  • TaskStatus. Un mecanismo que nos permite gestionar el estado de nuestro proceso. Si se encuentra en ejecución, qué medida de progreso tiene, en qué estado del proceso se encuentra, o requerir su cancelación si fuese necesario.
  • AbstractMonitorableTask. Una clase que extiende a Thread integrando con él un TaskStatus para su gestión.

Y en la clase ApplicationManager del plugin org.gvsig.app, encontraremos métodos que nos permiten:

  • Presentar mensajes en la barra de estado de la aplicación
  • Presentar cuadros de dialogo del tipo de showMessageDialog.
  • Presentar cuadros de dialogo del tipo de showConfirmDialog.
  • Presentar cuadros de dialogo del tipo de showInputDialog.
  • Construir componentes de swing
  • Presentar cuadros de dialogo al usuario

Todo ello asegurándose que estas tareas se ejecutan en el hilo de ejecución del manejador de swing de forma que no tengamos que preocuparnos por esto desde el hilo de nuestro proceso.

Además de estas herramientas, el entorno de andami esta pendiente de las instancias de TaskStatus que se van creando y presenta en la barra de estado de la aplicación información resumida de estas de forma automática, para que no tengamos que preocuparnos por generar interface de usuario para ellas si no queremos una presentación específica.

A lo largo de estos cuatro artículos veremos:

  1. Cuáles son los principales métodos y funcionalidad que nos ofrece el artefacto TaskStatus.
  2. Cuál podría ser la estructura de nuestro proceso y como lanzarlo desde una extensión.
  3. Cómo podríamos interactuar con el usuario de forma simple desde nuestro proceso.

En el próximo artículo, “Hilos y gvSIG (2 de 4): TaskStatus“,  continuaremos viendo cuáles son las principales funcionalidades que nos ofrecen las utilidades de TaskStatus.
Un saludo

Joaquín

Posted in development, gvSIG Desktop, spanish | Tagged | 1 Comment