当且仅当两个节点之间存在边缘时,我试图从每个节点图形对象到另一个节点图形对象绘制一条线。
我的图是在二维布尔邻接矩阵中实现的。
我该如何实现?
这是我到目前为止所做的:
// 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);
}
}
}
}
}
答案 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这样的图书馆(那里有很多图库,这些图库可能是最受欢迎的图库之一,但这里只应作为例子)