当我将 Swing 中的一条线应用于包含使用 Graphstream 创建的现有图形的组件时,我遇到了渲染/绘画问题。
问题是当鼠标被拖动并调用绘画方法时,底层图形被更新,整个帧闪烁,线条绘制不顺畅。
有没有办法冻结底层图形的渲染?
我尝试了几种方法,但似乎都产生了相同的结果。在最新示例下方,我尝试在视图上设置前布局渲染器。
我相信这是一个简单的问题,与在画布上绘图的方法不正确有关,而没有正确管理此前景层的重绘/渲染的并发或更新。
此外,如下所示,在添加我自己的自定义侦听器之前,我从图中删除了所有侦听器(否则在拖动鼠标时,graphstream 库会绘制边界框/选择矩形,或者拖动节点)。这里是否还有更好的方法来停用 graphstream 完成的绘图和鼠标交互。
import org.graphstream.graph.Graph;
import org.graphstream.graph.implementations.DefaultGraph;
import org.graphstream.ui.graphicGraph.GraphicGraph;
import org.graphstream.ui.swing_viewer.DefaultView;
import org.graphstream.ui.swing_viewer.SwingViewer;
import org.graphstream.ui.view.LayerRenderer;
import org.graphstream.ui.view.Viewer;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class LinesDrawingOnGraphExample extends JFrame {
static Point pointStart = null;
static Point pointEnd = null;
static LayerRenderer lineRenderer;
static DefaultView view;
public static void main(String args[]) throws Exception {
JFrame f = new JFrame("Draw a Red Line on graph");
f.setSize(300, 300);
f.setLocation(300, 300);
f.setResizable(false);
//build graph
Graph graph = new DefaultGraph("g");
graph.addNode("A");
graph.addNode("B");
graph.addNode("C");
graph.addNode("D");
graph.addNode("E");
graph.addNode("F");
graph.addNode("G");
graph.addNode("H");
graph.addNode("I");
graph.addEdge("AB", "A", "B");
graph.addEdge("BC", "B", "C");
graph.addEdge("CA", "C", "A");
//set viewer
Viewer viewer = new SwingViewer(graph, Viewer.ThreadingModel.GRAPH_IN_GUI_THREAD);
view = (DefaultView) viewer.addDefaultView(false);
viewer.enableAutoLayout();
viewer.replayGraph(graph);
//backup existing default graph listeners
MouseListener[] ml = ((DefaultView) viewer.getDefaultView()).getMouseListeners();
MouseMotionListener[] ml2 = ((DefaultView) viewer.getDefaultView()).getMouseMotionListeners();
//remove them (remove the bounding box which is drawn on mouse drag)
for (MouseListener mouseListener : ml) {
view.removeMouseListener(mouseListener);
}
for (MouseMotionListener mouseListener : ml2) {
view.removeMouseMotionListener(mouseListener);
}
//add new mouse listeners for drawing
MouseAdapter newListener = new DrawListener();
view.addMouseListener(newListener);
view.addMouseMotionListener(newListener);
//use graph forelayout for drawing the line
lineRenderer = new LayerRenderer<Graphics2D>() {
@Override
public void render(Graphics2D g, GraphicGraph graphicGraph, double v, int i, int i1, double v1, double v2, double v3, double v4) {
if (pointStart != null && pointEnd != null) {
g.setColor(Color.RED);
g.drawLine(pointStart.x, pointStart.y, pointEnd.x, pointEnd.y);
}
}
};
view.setForeLayoutRenderer(lineRenderer);
JPanel p = new JPanel(new BorderLayout());
p.add(view, BorderLayout.CENTER);
f.add(p);
f.setVisible(true);
}
private static class DrawListener extends MouseAdapter {
public void mousePressed(MouseEvent e) {
pointStart = e.getPoint();
}
public void mouseReleased(MouseEvent e) {
pointStart = null;
}
public void mouseDragged(MouseEvent e) {
pointEnd = e.getPoint();
view.render((Graphics2D) view.getGraphics());
}
}
}