Como impressionar seus amigos com Java

Postado em 05. dez, 2006 por Thadeu Russo em Java

Olá, já estou a algum tempo na Caelum mas só agora estreando no blog e, para compensar a demora, resolvi fazer um pouco diferente. O título deve estar chamando a atenção e antes de colocar o assunto de verdade (está bem, sei que estou valorizando um pouco), vou apenas lembrar da pessoa que me mostrou o assunto e da que me sugeriu colocar no blog. Ricardo e Paulo. Pronto, direto ao assunto.

Certamente muitos desenvolvedores Java já passaram pelo problema de ter de mostrar alguns recursos interessantes da plataforma. Certamente o HelloWorld não é um grande atrativo. Talvez demonstrar como é fácil fazer relacionamentos com tabelas associativas e chaves compostas através do Hibernate ajude bastante, mas ainda falta certo apelo visual.

Existe uma API feita em Java de livre uso, chamada Prefuse que utiliza-se do Java 2D para tornar simples tarefas complicadas visualmente, como por exemplo, renderizar grafos de maneira visualmente agradável e ainda por cima animada, permitindo inclusive uma interação do usuário através de drag-and-drop.

Uma aplicação mais prática e um tanto quanto útil, é a representação do relacionamento de tabelas ou mesmo de objetos, quando você precisa navegar entre uma grande quantidade de informações e quer uma maneira mais rápida em vez de pular de página em página. A idéia deste post é apenas fazer a introdução ao prefuse, sem entrar em muitos detalhes da API.

Veja abaixo o código para criar uma aplicação mostrando visualmente o relacionamento das fronteiras dos estados do Brasil.

/**
 * @author Thadeu Russo
 * 
 */
public class Visualizacao {
  
  /** Display onde será desenhada a visualização */
  private Display display;
  
  /** Lista de actions relacionadas ao layout */
  private ActionList layout;
  
  /** Lista de actions relacionada as cores */
  private ActionList color;
    
  /** renderizador dos labels */
  private LabelRenderer labelRenderer;
  
  /**
   * Carrega as informações que estao no 
   * arquivo sourceFile para um novo grafo
   * @param sourceFile
   * @return graph
   * @throws DataIOException no caso de 
   * problemas com a leitura dos dados
   * */
  private Graph loadGraph(String sourceFile) throws DataIOException{          
    return new GraphMLReader().readGraph(sourceFile);
  }
  
  
  /**
   * Este método retorna o display para a visualization informada 
   * @return display
   * @throws DataIOException 
   * */
  private Display getDisplay() throws DataIOException {
    Visualization visualization = this.buildVisualization(
                      this.loadGraph("data/brasil.xml")
                      );
    /** troquei a visualização? */
    if (this.display == null || !this.display.getVisualization().equals(visualization)) {
      this.display = new Display(visualization);
      this.display.setSize(720, 500);
      this.display.addControlListener(new DragControl());
      this.display.addControlListener(new PanControl());
      this.display.addControlListener(new ZoomControl());      
      this.display.addControlListener(new WheelZoomControl());
      this.display.pan(200, 350);
      this.display.setForeground(Color.GRAY);
      this.display.setBackground(Color.WHITE);
    }
    return this.display;
  }
  
  /**
   * Recupera as actions relacionadas ao layout
   * @return ActionList relacionados ao layout
   * */
  private ActionList getLayout() {
    if (this.layout == null) {
      this.layout = new ActionList(Activity.INFINITY);
      this.layout.add(new ForceDirectedLayout("graph"));
      this.layout.add(new RepaintAction());
    }
    return this.layout;
  }
   
  /**
   * Recupera a configuração de cores e actions relacionadas a esta
   * @return action list
   * */
  private ActionList getColor(){
    if (this.color == null) {
      DataColorAction fill = new DataColorAction("graph.nodes", "region",
          Constants.NOMINAL, VisualItem.FILLCOLOR, this
              .getColorPalette());      
      ColorAction text = new ColorAction("graph.nodes",
          VisualItem.TEXTCOLOR, ColorLib.gray(0));

      ColorAction edges = new ColorAction("graph.edges",
          VisualItem.STROKECOLOR, ColorLib.gray(200));

      this.color = new ActionList();
      color.add(fill);
      color.add(text);
      color.add(edges);
    }
    return this.color;
  }
  
  /**
   * Monta a visualização a ser mostrada no display
   * @param graph O grafo a ser renderizado
   * @return visualization
   * */
  private Visualization buildVisualization(Graph graph){
    Visualization visualization = new Visualization();
    visualization.add("graph", graph);    
    visualization.setRendererFactory(
        new DefaultRendererFactory(this.getLabelRenderer())
        );
    visualization.putAction("color", this.getColor());
    visualization.putAction("layout", this.getLayout());
    visualization.run("color");
    visualization.run("layout");    
    
    return visualization;
  }
  
  /**
   * Recupera o renderizador de rótulos (labels)
   * @return label renderer
   * */
  private LabelRenderer getLabelRenderer() {
    if (this.labelRenderer == null) {
      this.labelRenderer = new LabelRenderer("state");
      this.labelRenderer.setRoundedCorner(8, 8);
    }
    return this.labelRenderer;
  }  

  /**
   * Recupera a paleta de cores a ser usada na renderização
   * @return paleta de cores
   * */
  private int [] getColorPalette(){
    return new int[] { ColorLib.rgb(255, 128, 128),
        ColorLib.rgb(255, 128, 64), ColorLib.rgb(176, 176, 100),
        ColorLib.rgb(100, 255, 64), ColorLib.rgb(128, 255, 255) }; 
  }
  
  public static void main(String[] args) throws DataIOException {
    Visualizacao visualizacao = new Visualizacao();
    
    JFrame frame = new JFrame("Grafo do Mapa do Brasil por Regiões");    
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);    
    frame.add(visualizacao.getDisplay());
    frame.pack();
    frame.setVisible(true);
    
  }
}

Aqui, a informação para gerar o grafo apresentado é lida de um XML. Poderia ser muito bem carregada a partir de um banco de dados (interessante ler o metadata do banco para gerar relacionamento entre tabelas, não?). O código acima serve de boa base para você fazer sua própria aplicação. Creio que o prefuse seja uma opção bastante interessante em vez de usar tecnologias de visualização como Flash, onde você ainda teria o trabalho de fazer toda a integração, em vez de diretamente implementar listeners java.

E vocês, que APIs consideram interessantes para demonstrar o poder e em especial a simplicidade do Java?

Thadeu Russo

18 Respostas para “Como impressionar seus amigos com Java”

  1. Alberto Luiz

    05. dez, 2006

    Essa API é realmente muito boa, participo de um projeto no qual montamos a hierarquia de uma rede de computadores com o prefuse. No proprio vem com uns exemplos muito bons.

    Alberto

  2. Luiz Aguiar

    05. dez, 2006

    Caramba, muito legal isso ai hein… :)
    bacana, parabéns.

  3. ASOBrasil

    06. dez, 2006

    Não conhecia essa API, muito legal esse post. Parabéns!

  4. Fernando Boaglio

    12. dez, 2006

    Legal, muito bom.

    Para mostrar o poder do Java Desktop eu falo pra pessoa rodar o demo “SwingSet2″ que está dentro do diretório “demo” do JDK.

    cd C:\jdk\demo\jfc\SwingSet2
    java -jar SwingSet2.jar

  5. Ivan

    12. dez, 2006

    Citei este seu texto no meu blog, mas não sei se o trackback funcionou como o esperado.

    De qualquer maneira, parabéns pelo post!

  6. Thadeu Russo

    12. dez, 2006

    Fico contente que gostaram do post :)

    Espero estar mais tranquilo no ano que vem para escrever, pois me surgiram idéias muito legais e gostaria de compartilhas.

    []‘s a todos.

  7. José Henrique

    13. dez, 2006

    Você poderia postar o seu XML que você usou no seu exemplo? Estou tentando reproduzir seu exemplo aqui, mas não tenho o XML para testar :(

  8. Jean

    21. jun, 2007

    Estou tentando rodar o exemplo postado acima, mas não estou conseguindo, o que é necessário para rodar? Tb peguei o codigo do prefuse no site http://www.prefuse.org e não consigo abrir no netbeans como faço?

  9. Thadeu

    21. jun, 2007

    Quando vc faz o download do site do prefuse, precisa compilar e gerar o jar. Coloque o jar no classpath e depois, eh so alegria :)

  10. Wilma

    08. jul, 2007

    Também estou fazendo algumas pesquisas sobre o Prefuse mas estou com dificuldades em compílá-lo no NetBeans 5.5. Poderia me dar alguma dica?
    Se possível, gostaria de receber também o arquivo XML do teste acima.
    Agradeço.

  11. Daniela

    21. set, 2007

    Olá
    Gostaria de receber o XML do exemplo acima.
    []‘s

  12. Fernando

    07. out, 2007

    Olá, vc é massa mesmo heim….
    gostaria de uma dica, sobre grafo!!!!
    Não consigo validar um código que faça um grafo de arvore geradora
    de percurso minímo, pode me ajudar?

  13. Oswaldo Castro

    21. out, 2007

    Belo trabalho Thadeu

    Já estou com um monte de idéias para a utilização do prefuse (no site existe muita coisa também.

    Parabéns mais uma vez

    (Se possível também gostaria de obter o arquivo xml que Você usou. Pode ser?)

    Abraços

  14. Thadeu

    22. out, 2007

    Ola Oswaldo, teria como me pedir isso por email? thadeu.russo at caelum.com.br ?

  15. Antonio Lazaro

    30. abr, 2008

    Belo post Tadheu, entretando hoje o site do prefuse não dispõe seus arquivos para download.
    Você poderia me passar eles?
    Hoje, você usaria prefuse ou flex para construções desses componentes complexos como árvores,grafos..?

  16. Filipe Kovalski

    18. fev, 2009

    Link para o JNLP está quebrado =(

  17. Thadeu

    20. fev, 2009

    Oi Filipe, corrigido.. Obrigado pelo aviso!

  18. alberto

    12. jul, 2009

    Quero testar, mas preciso do arquivo XML, tem como postar?

Deixar uma Resposta