如何使用Graphics Class从顶点到顶点绘制一条线?

时间:2014-03-23 08:08:04

标签: java class graphics

当且仅当两个节点之间存在边缘时,我试图从每个节点图形对象到另一个节点图形对象绘制一条线。

我的图是在二维布尔邻接矩阵中实现的。

我该如何实现?

这是我到目前为止所做的:

// Draw method which will draw the shape of the graph.
    public void paint(Graphics g) {

        //Define parameters to draw the graph in. Example taken from
        //http://www.zetcode.com/gfx/java2d/basicdrawing/
        Dimension size = getSize();
        Insets insets = getInsets();

        int w = size.width - insets.left - insets.right;
        int h = size.height - insets.top - insets.bottom;

        //Parameters for vertices, to be used later to draw vertices.
        int x = 0;
        int y = 0;

        // Extend to Graphics 2D
        Graphics2D graph = (Graphics2D) g;

        // Set preferences. This cleans up edges.
        graph.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON);

        //Generate vertices as random points on JPanel.
        Random r = new Random();

        //Draw random points on JPanel for the vertices.
        for (int l = 0; l < adj_Matrix_Edges.length; l++){
            String str = Integer.toHexString(l);
            //Define where a specific vertex will fall on a x, y coordinate
            //inside the container.
            x = Math.abs(r.nextInt()) % w;
            y = Math.abs(r.nextInt()) % h;
            //Initialize a node graphics object to represent vertices.
            Graphics2D node = (Graphics2D)g;
            node.fillOval(x, y, 7, 7); //Creates filled ovals for nodes.
            graph.drawString(str, x, y + 20);
        }

            //Create a nexted for loop to see if there is an edge between vertices.
        for (int m = 0; m < adj_Matrix_Edges.length; m++){
            for (int n = 0; m < adj_Matrix_Edges[m].length; m++){
                if (adj_Matrix_Edges[m][n]){
                    graph.drawLine(node, y1, x2, y2);
                }
            }
        }

    }
}

1 个答案:

答案 0 :(得分:2)

正如MadProgrammer已经提到的,继承自JComponent的类中的绘制过程通常在paintComponent方法中完成:

@Override
protected void paintComponent(Graphics gr)
{
    super.paintComponent(gr);
    Graphics2D g = (Graphics2D)g;

    // Your drawing stuff goes here....
}

但是关于实际问题:我假设您想要绘制图形(或更准确地说:节点链接图)。这项任务有许多很复杂的库。除了最简单的应用程序之外,我强烈建议使用这样的库,因为手动执行此操作可能会变得相当棘手。

但是,目前的主要问题是每次重新绘制组件时都会创建新的随机点!我想知道这是什么样的。调整组件大小时,您应该会看到奇怪的闪烁点。

你必须以某种方式存储点(它们的坐标),以便稍后在这些点之间绘制线条。

只需对代码进行少量修改即可实现此目的:

//Generate vertices as random points on JPanel.
// Pass "0" as the argument to the constructor of Random, so that it 
// will always create the same sequence of random numbers
Random r = new Random(0);

// Create lists that will store the point coordinates
List<Integer> pointsX = new ArrayList<Integer>();
List<Integer> pointsY = new ArrayList<Integer>();

for (int l = 0; l < adj_Matrix_Edges.length; l++){
    String str = Integer.toHexString(l);
    //Define where a specific vertex will fall on a x, y coordinate
    //inside the container.
    x = Math.abs(r.nextInt()) % w;
    y = Math.abs(r.nextInt()) % h;

    // Store the coordinates of the points:
    pointsX.add(x);
    pointsY.add(y);

    //Initialize a node graphics object to represent vertices.
    Graphics2D node = (Graphics2D)g;
    node.fillOval(x, y, 7, 7); //Creates filled ovals for nodes.
    graph.drawString(str, x, y + 20);
}

//Create a nexted for loop to see if there is an edge between vertices.
for (int m = 0; m < adj_Matrix_Edges.length; m++){
    for (int n = 0; m < adj_Matrix_Edges[m].length; m++){
        if (adj_Matrix_Edges[m][n]){

            // Fetch the coordinates of the points from the list
            int xm = pointsX.get(m);
            int ym = pointsY.get(m);
            int xn = pointsX.get(n);
            int yn = pointsY.get(n);
            graph.drawLine(xm,ym,xn,yn);
        }
    }
}

但我建议这样做。这只是一个快速的黑客,以显示如何通过对代码的最小修改来实现这一目标。通常,绘制时应 NOT 构建任何数据结构。绘画代码应尽可能简短。

相反,您应该在初始化邻接矩阵时创建表示节点的数据结构。你至少可以创建一些像

这样的类
class Node
{
    String name;
    // Coordinates, between 0 and 1
    double x;
    double y;
}

在声明和初始化adj_Matrix_Edges的地方,您还可以创建一个节点列表,如下所示:

boolean adj_Matrix_Edges[][];
List<Node> nodes;

void initializeMatrix()
{
    adj_Matrix_Edges = ...;

    // Create the nodes
    Random random = new Random(0);
    nodes= new ArrayList<Node>();
    for (int m = 0; m < adj_Matrix_Edges.length; m++)
    {
        Node node= new Node();
        node.name = Integer.toHexString(m);
        node.x = random.nextDouble(); 
        node.y = random.nextDouble(); 
        nodes.add(node);
    }
}

稍后,当您进行绘制时,您可以访问这些节点并直接绘制它们:

@Override
protected void paintComponent(Graphics gr)
{
    super.paintComponent(gr);
    Graphics2D g = (Graphics2D)g;

    for (int l = 0; l < adj_Matrix_Edges.length; l++){

        // Compute the x- and y-coordinates that the
        // node will have in this component. (That's 
        // why the coordinates that are stored in 
        // the "Node" class should always be 
        // between 0 and 1!)

        Node node = nodes.get(l);
        int ix = (int)(node.x * getWidth());
        int iy = (int)(node.y * getHeight());

        g.fillOval(ix, iy, 7, 7);
        graph.drawString(node.name, ix, iy + 20);
    }

    //Create a nested for loop to see if there is an edge between vertices.
    for (int m = 0; m < adj_Matrix_Edges.length; m++){
        for (int n = 0; m < adj_Matrix_Edges[m].length; m++){
            if (adj_Matrix_Edges[m][n]){

                Node nodeM = nodes.get(m);                    
                Node nodeN = nodes.get(n);
                int xm = (int)(nodeM.x * getWidth());
                int ym = (int)(nodeM.y * getHeight());
                int xn = (int)(nodeN.x * getWidth());
                int yn = (int)(nodeN.y * getHeight());
                graph.drawLine(xm,ym,xn,yn); 
            }
        }
    }
 }

通常,你也会有一个 edge 的表示,它类似于我在上面概述的Node类,但是你正在慢慢接近那些证明使用a的合理性。像JUNG http://jung.sourceforge.net/或JGraphX https://github.com/jgraph/jgraphx这样的图书馆(那里有很多图库,这些图库可能是最受欢迎的图库之一,但这里只应作为例子)