Home » Java » JGraph » Tutorial JGraph – parte 2 – Begin End

Tutorial JGraph – parte 2 – Begin End

Partindo do pressuposto que todos sabem o que são grafos e já leram o manual do usuário, podemos já apresentar um exemplo de código e identificar um de seus conceitos mais polêmicos .

Exemplo 1

mxGraph graph = new mxGraph();
Object parent = graph.getDefaultParent();

graph.getModel().beginUpdate();
try
{
 Object v1 = graph.insertVertex(parent, null, "Brazil", 100, 100, 50, 40);
 Object v2 = graph.insertVertex(parent, null, "Soccer", 240, 150, 50, 40);
 graph.insertEdge(parent, null, "loves", v1, v2);
}
finally
{
 graph.getModel().endUpdate();
}
mxGraphComponent graphComponent = new mxGraphComponent(graph);
getContentPane().add(graphComponent);

Já vi muitas vezes ser apresentado, de forma errônea, a necessidade de se ter os métodos beginUpdate e endUpdate circundando a criação de células (vértices e arestas[verão nos próximos artigos porque as chamarei assim] ).

O JGraph é capaz de armazenar todas as alterações feitas em suas células (veja padrão memento), ou seja, se o usuário move, redimensiona, cria, remove (etc) uma célula, tal ação é memorizada e passível de ser revertida (undo e redo), algo semelhante ao que acontece em um editor de texto. No entanto, se for feita uma animação com as células e alterações parciais acontecerem, não se desejará que todas as alterações sejam desfeitas em ordem inversa até chegar ao início da animação. Nesse momento devemos utilizar o par  beginUpdate e endUpdate, estes são métodos da classe mxGraphModel(documentação JavaScript) e estabelecem uma transação única. Assim todas as alterações (eventos) que houver serão tratados como uma única transação, conceito parecido com o mecanismo BEGIN TRANSACTION / COMMIT – ROLLBACK  do SQL.

Logo, o menor programa funcional, seria algo como:

Exemplo 2

package src.aleks.jgraph;

import com.mxgraph.swing.mxGraphComponent;
import com.mxgraph.view.mxGraph;
import javax.swing.JFrame;

public class Example1 extends JFrame {

public Example2() {
  super("Example 2");

  mxGraph graph = new mxGraph();
  Object parent = graph.getDefaultParent();

  Object v1 = graph.insertVertex(parent, null, "Brazil", 100, 100, 50, 40);
  Object v2 = graph.insertVertex(parent, null, "Soccer", 240, 150, 50, 40);
  graph.insertEdge(parent, null, "loves", v1, v2);
  mxGraphComponent graphComponent = new mxGraphComponent(graph);
  getContentPane().add(graphComponent);
}

public static void main(String[] args) {
  Example2 frame = new Example2();
  frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  frame.setSize(400, 320);
  frame.setVisible(true);
}

}

Exemplo 3

Exemplo3

A imagem acima é da aplicação jgraphxExample3 (código logo abaixo e projeto com download disponível). Os 2 primeiros botões executam o undo e redo, apagando as alterações feitas ou refazendo-as. Já os outros 2 botões, na extrema direita, criam  2 células e 1 vértice unindo-as, porém o primeiro como múltiplas transações e o segundo dentro de uma transação única .

Além disso tal aplicação, já 100% funcional, será a base para explorar outros aspectos nos artigos seguintes.


package src.aleks.jgraph;

import com.mxgraph.swing.mxGraphComponent;
import com.mxgraph.util.mxEvent;
import com.mxgraph.util.mxEventObject;
import com.mxgraph.util.mxEventSource;
import com.mxgraph.util.mxUndoManager;
import com.mxgraph.util.mxUndoableEdit;
import com.mxgraph.view.mxGraph;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.AbstractButton;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JSeparator;
import javax.swing.JToolBar;

public class Example3 extends JFrame {

mxUndoManager undoMgr = new mxUndoManager();
 mxGraph graph = new mxGraph();
 JToolBar toolBar = new JToolBar();

public Example3() {
 super("JGraphX");

Object parent = graph.getDefaultParent();

Object v1 = graph.insertVertex(parent, null, "Brazil", 100, 100, 50, 40);
 Object v2 = graph.insertVertex(parent, null, "Soccer", 240, 150, 50, 40);
 graph.insertEdge(parent, null, "loves", v1, v2);
 mxGraphComponent graphComponent = new mxGraphComponent(graph);

mxEventSource.mxIEventListener listener = new mxEventSource.mxIEventListener() {
 @Override
 public void invoke(Object sender, mxEventObject evt) {
 undoMgr.undoableEditHappened((mxUndoableEdit) evt.getProperty("edit"));
 }
 };

//Quando um evento UNDO acontecer o mesmo será memorizado
 graph.getModel().addListener(mxEvent.UNDO, listener);
 graph.getView().addListener(mxEvent.UNDO, listener);

getContentPane().add(graphComponent);
 }

public static void main(String[] args) {
 Example3 frame = new Example3();
 frame.initToolbar();

frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
 frame.setSize(600, 500);
 frame.setVisible(true);
 }

/**
 * Inicializa a barra de menu
 */
 public void initToolbar() {

//Undo
 addToolbarButton("undo", "/resources/icons/undo.jpg", new AbstractAction() {
 @Override
 public void actionPerformed(ActionEvent ae) {
 if (undoMgr.canUndo()) {
 undoMgr.undo();
 }
 }
 });

//Redo
 addToolbarButton("redo", "/resources/icons/redo.jpg", new AbstractAction() {
 @Override
 public void actionPerformed(ActionEvent ae) {
 if (undoMgr.canRedo()) {
 undoMgr.redo();
 }
 }
 });

//Separador
 toolBar.add(new JSeparator(JSeparator.HORIZONTAL));

//Cria as células armazenando múltiplos eventos.
 addToolbarButton("single", "/resources/icons/single.jpg", new AbstractAction() {
 @Override
 public void actionPerformed(ActionEvent ae) {
 createCells("red");

}
 });

//Cria as células aramazenando como uma transição única.
 addToolbarButton("Beg-End", "/resources/icons/multiple.jpg", new AbstractAction() {
 @Override
 public void actionPerformed(ActionEvent ae) {
 graph.getModel().beginUpdate();
 try {
 createCells("yellow");
 } finally {
 graph.getModel().endUpdate();
 }
 }
 });

add(toolBar, BorderLayout.PAGE_START);
 }

public void addToolbarButton(String text, String icon, AbstractAction action) {
 JButton b = new JButton(text, new ImageIcon(getClass().getResource(icon)));
 b.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
 b.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
 toolBar.add(b);
 b.addActionListener(action);
 }

public void createCells(String color) {
 int len = graph.getChildCells(graph.getDefaultParent()).length;

Object v1 = graph.insertVertex(graph.getDefaultParent(), null, "Rectangle " + (len + 1), len * 10, len * 10, 100, 40, "fillColor=" + color);
 Object v2 = graph.insertVertex(graph.getDefaultParent(), null, "Rectangle " + (len + 1), 170 + len * 10, len * 10, 100, 40, "fillColor=" + color);
 graph.insertEdge(graph.getDefaultParent(), null, "join", v1, v2);
 }

}

Outro fato muito importante  a observar é que o endUpdate deve estar dentro da cláusula finally e não da cláusula catch, com isso mesmo ocorrendo uma exceção na manipulação das células, a transação será concluída. Nunca coloque endUpdate no código catch para não “desalinhar” os eventos armazenados.

 

Download – projetos Netbeans

Sugira novos artigos, aí logo em baixo…

6804 Total 5 Visualizações

About 

System development consultant
He graduated from UFF in Software development
A lot of experience in development process and management .
International expertise : USA (1 yr) and Italy (3 yrs) where He played as system team leader .
Fluently in italian and english.
He Lives now in Rio de Janeiro, Brazil

    Find more about me on:
  • googleplus
, ,