我正在使用Jacc生成的解析器来构造AST。在解析器中,我创建了一个JGraphT可听图:
public ListenableGraph<Expr, DefaultEdge> listenableGraph =
new DefaultListenableGraph<>(graph);
并在解析时添加AST节点:
public Expr addNode(Expr node)
{
listenableGraph.addVertex(node);
if (node instanceof BinExpr)
{
listenableGraph.addEdge(node,
((BinExpr)node).getLeft(),
new LabeledEdge());
listenableGraph.addEdge(node,
((BinExpr)node).getRight(),
new LabeledEdge());
}
else if (node instanceof Calc)
{
listenableGraph.addEdge(node,
((Calc)node).getAst(),
new LabeledEdge());
}
else if (node instanceof UnaryExpr)
{
listenableGraph.addEdge(node,
((UnaryExpr)node).getValue());
}
else if (node instanceof Value)
{
listenableGraph.addEdge(node,
((Value)node).getLiteral());
}
return node;
}
我正在使用JGraphx和Swing显示我的AST。它可以工作,但是我想在添加第一个节点时显示该图,并在每次添加节点时对其进行更新。这是我的代码
import java.io.*;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import com.mxgraph.layout.*;
import com.mxgraph.swing.*;
import org.jgrapht.*;
import org.jgrapht.ext.*;
import org.jgrapht.graph.*;
import org.jgrapht.event.*;
public class Main implements GraphListener<Expr, DefaultEdge>, ActionListener
{
Parser parser;
String expression;
JTextField text = new JTextField();
mxGraphComponent component;
JGraphXAdapter<Expr, DefaultEdge> jgxAdapter;
JPanel pane = new JPanel();
JPanel innerPane = new JPanel();
JButton button = new JButton("Eval");
JFrame frame = new JFrame("AST");
@Override
public void edgeAdded(GraphEdgeChangeEvent<Expr, DefaultEdge> e)
{
jgxAdapter.getView().reload();
innerPane.repaint();
innerPane.revalidate();
}
@Override
public void edgeRemoved(GraphEdgeChangeEvent<Expr, DefaultEdge> e)
{
jgxAdapter.getView().reload();
innerPane.repaint();
innerPane.revalidate();
}
@Override
public void edgeWeightUpdated(GraphEdgeChangeEvent<Expr, DefaultEdge> e)
{
}
@Override
public void vertexAdded(GraphVertexChangeEvent<Expr> e)
{
jgxAdapter.getView().reload();
innerPane.repaint();
innerPane.revalidate();
}
@Override
public void vertexRemoved(GraphVertexChangeEvent<Expr> e)
{
jgxAdapter.getView().reload();
innerPane.repaint();
innerPane.revalidate();
}
public void actionPerformed(ActionEvent e)
{
System.out.println(text.getText());
parser = new Parser(new StringReader(text.getText()));
parser.listenableGraph.addGraphListener(this);
jgxAdapter = new JGraphXAdapter<>(parser.listenableGraph);
jgxAdapter.setLabelsClipped(true);
mxCompactTreeLayout layout =
new mxCompactTreeLayout(jgxAdapter);
if(!(component == null))
{
innerPane.remove(component);
}
component = new mxGraphComponent(jgxAdapter);
component.setMinimumSize(new Dimension(Integer.MAX_VALUE, 260));
innerPane.add(component);
parser.lexer.nextToken();
parser.parse();
layout.setHorizontal(false);
layout.execute(jgxAdapter.getDefaultParent());
}
public static void main(String args[])
{
Main main = new Main();
main.text.setMaximumSize(new Dimension(Integer.MAX_VALUE, 16));
main.button.setMaximumSize(new Dimension(Integer.MAX_VALUE, 16));
main.button.addActionListener(main);
BoxLayout grid = new BoxLayout(main.pane, BoxLayout.Y_AXIS);
main.pane.setLayout(grid);
main.frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
main.frame.getContentPane().add(main.pane);
main.pane.add(main.innerPane);
main.innerPane.setLayout(new BorderLayout(0, 0));
main.pane.add(main.text);
main.pane.add(main.button);
main.frame.setMinimumSize(new Dimension(600, 400));
main.frame.pack();
main.frame.setVisible(true);
}
}
这确实有效,但是仅在添加所有节点后才显示AST。我的尝试是使用图侦听器并处理vertexAdded事件以使用repaint()和revalidate()更新图。捕获了事件,但只有在添加所有节点后,才会更新图摆动组件。