我需要在我的 java 小程序的边缘添加权重。当他/她在 2 个顶点之间创建边时,我需要用户输入它。
因此,基本上,当我绘制两个顶点然后动态添加边时,那时我应该能够在其上输入权重(文本框或弹出窗口输入值)。我不知道我会怎么做。谁能帮帮我。
要运行以下代码,请将参数“pos”添加为“nodeid:xPos,yPos;nodeid:xPos,yPos”,例如对于 2 个节点,我可以添加:“1:0,1;2:1,0”
编辑:我知道有一个名为“drawString("text",pos1,pos2)"的方法,但我不知道当小程序已经运行时如何动态获取文本。
这是我到目前为止所做的:
import javax.swing.*;
import java.awt.event.*;
import java.awt.geom.AffineTransform;
import java.awt.*;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
/**
Manual usage in Eclipse :
Add parameter "pos" as "nodeid:xPos,yPos;nodeid:xPos,yPos:
**/
public class MainGraph extends JApplet {
private static final long serialVersionUID = 1L; // default serial version
public void init() {
setPreferredSize(new Dimension(1000, 1000));
}
public void start() {
GraphPanel gp = new GraphPanel(getParameter("pos"));
getContentPane().add(new JScrollPane(gp.listOfNodes), BorderLayout.EAST);
getContentPane().add(new JScrollPane(gp), BorderLayout.CENTER);
}
public static void main(String[] args) {
new MainGraph().init();
}
}
class GraphPanel extends JPanel implements ActionListener {
private static final long serialVersionUID = 1L;
NodeList listOfNodes; // panel on right
JTextArea status; // status box for feedback
JTextField name; // user supplies name to identify graph
JButton submitName; // and submits
JPopupMenu popDelete; // popup asking to confirm edge deletion (upon right-click)
ArrayList<Edge> edgesToDelete = new ArrayList<Edge>(); // list of edges for user to choose which to remove from popup
final Map<Integer, Node> nodes = new HashMap<Integer, Node>(); // maintains all the nodes in the graph
final ArrayList<Edge> edges = new ArrayList<Edge>(); // list of links for processing algorithm
int connectToNode = 0; // for drawing edges -- this specifies other node to which to draw the edge
Point pressed = new Point(0, 0); // for selecting nodes -- this is point at which mouse is pressed
Node lineNode; // for live line drawing -- actively follow cursor with line from this node until other node is selected
Point cursor = new Point(0, 0); // -- where cursor is at present time
public GraphPanel(String pos) {
setBackground(Color.lightGray);
setBorder(BorderFactory.createLineBorder(Color.black));
listOfNodes = new NodeList(pos);
status = new JTextArea();
JTextArea infoName = new JTextArea("graph Name: ");
name = new JTextField(11);
submitName = new JButton("Submit Graph");
submitName.addActionListener(this);
popDelete = new JPopupMenu();
add(infoName);
add(this.name);
add(this.submitName);
add(this.status);
status.setText("Select a node to add it. Click two nodes to draw an edge. Scroll down to click \"Submit Graph\" when done.");
status.setDisabledTextColor(Color.black);
status.setEnabled(false);
infoName.setDisabledTextColor(Color.black);
infoName.setEnabled(false);
addMouseListener(new MouseHandler());
addMouseMotionListener(new MouseMotionHandler());
}
public void addNode(String label, int selfNodeId, int connectedNodeId, Point location) {
Node n = new Node(label, selfNodeId, connectedNodeId, location.x, location.y); // construct a new node object
nodes.put(selfNodeId, n); // and add to map using ID as key
status.setText("Added node " + selfNodeId + " at (" + location.x + ", " + location.y + ")");
repaint();
}
public void removeNode(int nodeId) {
for (Node n : nodes.values()) {
n.connectedNodeIds.remove((Integer) nodeId); // remove connections to node
}
nodes.remove((Integer) nodeId); // remove node
status.setText("Removed node " + nodeId);
repaint();
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
if (connectToNode > 0) g.drawLine(lineNode.xc, lineNode.yc, cursor.x, cursor.y);
for (Node n : nodes.values()) {
g.setColor(Color.darkGray);
if (n == lineNode) g.setColor(Color.black);
else if (n.connectedNodeIds.size() != 0) g.setColor(Color.blue);
else {
for (Node o : nodes.values()) {
if (o.connectedNodeIds.contains((Integer) n.selfNodeId)) {
g.setColor(Color.blue);
break;
}
}
}
g.fillOval(n.circle.x, n.circle.y, n.circle.width, n.circle.height);
g.drawString(n.label, n.circle.x, n.circle.y);
for (int connectedNode : n.connectedNodeIds) {
Node n2 = nodes.get(connectedNode);
// drawing edge
g.drawLine(n.xc, n.yc, n2.xc, n2.yc);
// drawing direction
AffineTransform tx = new AffineTransform();
Polygon arrow = new Polygon();
arrow.addPoint(0, 5); // first make arrow shape
arrow.addPoint(-5, -5);
arrow.addPoint(5, -5);
tx.setToIdentity();
tx.translate(n2.xc / 2, n2.yc / 2); // then translate arrow to midpoint
tx.translate(n.xc / 2, n.yc / 2);
double theta = Math.atan2(n2.yc-n.yc, n2.xc-n.xc);
tx.rotate(theta-Math.PI/2);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setTransform(tx); // apply transform
g2d.fill(arrow);
g2d.dispose();
}
}
}
private class MouseHandler extends MouseAdapter {
@Override
public void mousePressed(MouseEvent e) {
pressed = e.getPoint();
status.setText("Clicked: " + pressed.x + ", " + pressed.y);
if (e.getButton() == MouseEvent.BUTTON3) { // if right-click
edgesToDelete.clear();
popDelete.removeAll();
int i = 0;
for (Node n : nodes.values()) {
for (int connectedNode : n.connectedNodeIds) {
Node n2 = nodes.get(connectedNode);
if (pressed.x <= Math.max(n2.xc, n.xc) + 5 && pressed.x > Math.min(n2.xc, n.xc) - 5 && pressed.y <= Math.max(n2.yc, n.yc) + 5 && pressed.y > Math.min(n2.yc, n.yc) - 5) {
// if the click is near an edge
JMenuItem deleteEdge = new JMenuItem();
deleteEdge.setText(i + ": Delete edge " + n.selfNodeId + " to " + connectedNode + "?");
i++;
deleteEdge.addActionListener(GraphPanel.this);
popDelete.add(deleteEdge);
edgesToDelete.add(new Edge(n, nodes.get(connectedNode), 1));
}
}
}
popDelete.show(e.getComponent(), pressed.x, pressed.y);
popDelete.validate();
}
boolean nodeSelected = false;
for (Node n : nodes.values()) {
if (n.contains(pressed)) {
nodeSelected = true;
status.setText("Node " + n.selfNodeId + " selected");
if (connectToNode != 0 && connectToNode != n.selfNodeId) { // verify another node is being connected to this one
if (!lineNode.connectedNodeIds.contains(n.selfNodeId)) lineNode.connectedNodeIds.add(n.selfNodeId);
status.setText("Connecting node " + connectToNode + " to " + n.selfNodeId);
connectToNode = 0;
lineNode = null;
} else if (connectToNode == 0) { // or start the connection with this node
status.setText("Now select node to connect.");
connectToNode = n.selfNodeId;
lineNode = nodes.get(connectToNode);
} else {
connectToNode = 0; // user clicked self node, so cancel edge drawing
lineNode = null;
}
break;
}
}
if (!nodeSelected) {
connectToNode = 0; // user clicked away from nodes, so cancel edge drawing
lineNode = null;
}
e.getComponent().repaint();
}
}
private class MouseMotionHandler extends MouseMotionAdapter {
@Override
public void mouseMoved(MouseEvent e) {
cursor = e.getPoint();
e.getComponent().repaint();
}
}
@Override
public void actionPerformed(ActionEvent e) {
String action = e.getActionCommand();
if (action.equals("Submit Graph")) {
status.setText("Processing...");
ArrayList<Node> nodesToProcess = new ArrayList<Node>();
ArrayList<Edge> edgesToProcess = new ArrayList<Edge>();
for (Node n : nodes.values()) {
nodesToProcess.add(n);
for (int n2 : n.connectedNodeIds) {
edgesToProcess.add(new Edge(n, nodes.get(n2), 1));
}
}
} else {
int edgeIndex = Integer.parseInt(e.getActionCommand().split(":")[0]);
Edge edgeToDelete = edgesToDelete.get(edgeIndex);
nodes.get(edgeToDelete.node1).connectedNodeIds.remove(edgeToDelete.node2.selfNodeId); // delete connected node from node information (corresponding to edge)
status.setText("Edge " + edgeToDelete.node1 + " to " + edgeToDelete.node2 + " deleted.");
}
}
class NodeList extends JPanel implements ActionListener {
private static final long serialVersionUID = 1L;
String[] positions;
//JButton btnSubmit = new JButton("Submit Graph");
NodeList(String pos) {
setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
setBackground(Color.darkGray);
positions = pos.split(";");
for (String idPosPair : positions) { // idPosPair has form id:x,y
String id = idPosPair.split(":")[0];
Point xy = whereIsNode(Integer.parseInt(id));
JButton addNode = new JButton();
addNode.setLayout(new BorderLayout());
addNode.add(BorderLayout.NORTH, new JLabel("Node" + id));
addNode.add(BorderLayout.SOUTH, new JLabel("(" + (xy.x-30)/50 + ", " + (xy.y-30)/50 + ")"));
addNode.setActionCommand(id);
addButton(addNode);
}
//addButton(btnSubmit);
}
public void addButton(JButton button) {
button.setAlignmentX(CENTER_ALIGNMENT);
button.addActionListener(this);
add(button);
}
private Point whereIsNode(int nodeId) {
for (String idPosPair : positions) {
if (idPosPair.startsWith(nodeId + ":")) {
String[] xy = idPosPair.split(":")[1].split(",");
int x = 50*Integer.parseInt(xy[0])+30;
int y = 50*Integer.parseInt(xy[1])+30;
return new Point(x, y);
}
}
return new Point(0, 0);
}
@Override
public void actionPerformed(ActionEvent e) {
String action = e.getActionCommand();
int nodeId = Integer.parseInt(action);
if (nodes.containsKey(nodeId)) {
removeNode(nodeId);
status.setText("Removing node...");
} else {
addNode("Node" + action, nodeId, 0, whereIsNode(nodeId));
status.setText("Adding node...");
}
}
}
}
class Node {
public Rectangle circle; // nodes are drawn as filled circles on invisible rectangular areas
public String label; // string displayed on circle
public int selfNodeId; // keep track of self
public ArrayList<Integer> connectedNodeIds = new ArrayList<Integer>(); // transmitting to these nodes
public int r = 15; // radius
public int xc; // center
public int yc;
public Node(String label, int selfNodeId, int connectedNodeId, int x, int y) {
circle = new Rectangle();
this.label = label;
this.selfNodeId = selfNodeId;
if (connectedNodeId != 0) connectedNodeIds.add(connectedNodeId);
circle.setLocation(x, y);
circle.setBounds(x - r, y - r, 2*r, 2*r);
xc = x + r/2;
yc = y + r/2;
}
public boolean contains(Point xy) {
return circle.contains(xy);
}
public void updateLocation(int dx, int dy) {
circle.x += dx;
circle.y += dy;
xc = circle.x + r/2;
yc = circle.y + r/2;
}
}
class Edge { // keeps track of edges (nodes and link quality between them) for processing algorithm
public Node node1;
public Node node2;
public float link;
public Edge(Node node1, Node node2, float link) {
this.node1 = node1;
this.node2 = node2;
this.link = link;
}
public String toString() {
return "(" + node1.selfNodeId + ", " + node2.selfNodeId + ", " + link + ")";
}
}