1

当我将 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());
        }
    }
}
4

0 回答 0