📄 graphpanel.java
字号:
package cq_result_trans.application;
import java.util.*;
import java.awt.*;
import java.awt.event.*;
import mddb.client.*;
import javax.swing.*;
import java.awt.geom.*;
import mddb.client.*;
import mddb.client.components.*;
class Node {
double x, y; //位置坐标
static final int radius = 12; //半径
String lbl; //方块中的文字
ClientNode mapNode;
}
class Edge {
int from;
int to;
double len;
int edgeType; //用于标示边的类型
public static final int TYPE_MEMBER = 1;
public static final int TYPE_NEIGHBOUR = 2;
public static final int TYPE_GETWAY = 3;
}
public class GraphPanel
extends JPanel
implements Runnable, MouseListener, MouseMotionListener {
DemoManger demoManger;
//设定点集
int nnodes = 0; //已有的节点数量
Node nodes[] = new Node[100]; //----------注意:其中Nodes[0]是Car节点!!!
//设定边集
int nedges = 0; //已有的边的数量
Edge edges[] = new Edge[200];
Node pick;
Image offscreen;
Dimension offscreensize;
Graphics offgraphics;
//constractor---------------------------------------------------------------
public GraphPanel( DemoManger dManger ) {
demoManger = dManger;
setBackground( SystemColor.info );
//设定弹出式窗口
addMouseListener( this );
addMouseMotionListener( this );
ToolTipManager toolTipManager = ToolTipManager.sharedInstance();
toolTipManager.setInitialDelay( 10 );
toolTipManager.setReshowDelay( 100 );
toolTipManager.setDismissDelay( 50000 );
}
public void run() {
int counter = 0; //用来使各个表的更新速度减慢为1s更新一次
while( true ) {
counter++;
//对各个面板进行更新
if( counter == 10 ) {
if( demoManger.frame.groupResultPanel.isShowing ) {
demoManger.frame.groupResultPanel.updatePanel( nnodes,
nodes );
}
else if( demoManger.frame.routineResultPanel.isShowing ) {
demoManger.frame.routineResultPanel.updatePanel();
}
else if( demoManger.frame.cqResultTransPanel.isShowing ) {
demoManger.frame.cqResultTransPanel.updatePanel();
}
counter = 0;
}
repaint();
try {
Thread.sleep( 100 );
}
catch( InterruptedException ie ) {
break;
}
}
}
//--------------------------------------------------------------------------
//寻找指定名字(ID号)
int findNode( String lbl ) {
for( int i = 0; i < nnodes; i++ ) {
if( nodes[i].lbl.equals( lbl ) ) {
return i;
}
}
return -1;
}
//随机版的addNode
int addNode( ClientNode mapedNode ) {
Node n = new Node();
n.x = mapedNode.getPosition().getX();
n.y = mapedNode.getPosition().getY();
n.lbl = String.valueOf( mapedNode.getID() );
n.mapNode = mapedNode;
nodes[nnodes] = n;
return nnodes++;
}
void addEdge( String from, String to, int len, int type ) {
Edge e = new Edge();
e.from = findNode( from );
e.to = findNode( to );
e.len = len;
e.edgeType = type;
edges[nedges++] = e;
}
//--------------------------------------------------------------------------
final Color masterColor = Color.red;
final Color nodeColor = new Color( 250, 220, 100 );
final Color selectColor = Color.pink;
final Color edgeColor = Color.black;
final Color stressColor = Color.darkGray;
final Color memberColor = Color.black;
final Color neighbourColor = Color.pink;
final Color getwayColor = Color.red;
//--------------------------------------------------------------------------
public void paintNode( Graphics g, Node n, FontMetrics fm ) {
int x = ( int )n.x;
int y = ( int )n.y;
Graphics2D g2 = ( Graphics2D )g;
g2.setColor( ( n == pick ) ? selectColor :
( n.mapNode.isMaster() ? masterColor : nodeColor ) );
int w = fm.stringWidth( n.lbl ) + 10;
int h = fm.getHeight() + 4;
//画出覆盖范围
int validRange = n.mapNode.getValidRange();
Ellipse2D.Double ellipse2d = new Ellipse2D.Double( x -
validRange,
y - validRange,
2 * validRange,
2 * validRange );
g2.draw( ellipse2d );
int marginLen = 10; //这是打印两个字符串的长度
//画出节点
ellipse2d = new Ellipse2D.Double( x - Node.radius, y - Node.radius,
Node.radius * 2, Node.radius * 2 );
g2.fill( ellipse2d );
//g2.fillRect( x - marginLen, y - marginLen, marginLen*2, marginLen*2 );
g2.setColor( Color.black );
g2.draw( ellipse2d );
//g2.drawRect( x - marginLen, y - marginLen, marginLen*2, marginLen*2 );
g2.drawString( n.lbl, x - ( w - 10 ) / 2,
( y - ( h - 4 ) / 2 ) + fm.getAscent() );
}
//public synchronized void update( Graphics g ) {
public void paintComponent( Graphics g ) {
super.paintComponent( g );
Dimension d = getSize();
if( ( offscreen == null ) || ( d.width != offscreensize.width ) ||
( d.height != offscreensize.height ) ) {
offscreen = createImage( d.width, d.height );
offscreensize = d;
if( offgraphics != null ) {
offgraphics.dispose();
}
offgraphics = offscreen.getGraphics();
offgraphics.setFont( getFont() );
}
offgraphics.setColor( getBackground() );
offgraphics.fillRect( 0, 0, d.width, d.height );
updateEdges(); //Line 199
for( int i = 0; i < nedges; i++ ) {
Edge e = edges[i];
int x1 = ( int )nodes[e.from].x;
int y1 = ( int )nodes[e.from].y;
int x2 = ( int )nodes[e.to].x;
int y2 = ( int )nodes[e.to].y;
int len = ( int )Math.sqrt( ( x1 - x2 ) * ( x1 - x2 ) +
( y1 - y2 ) * ( y1 - y2 ) );
offgraphics.setColor( ( e.edgeType == Edge.TYPE_MEMBER ) ?
memberColor :
( e.edgeType == Edge.TYPE_NEIGHBOUR ?
neighbourColor : getwayColor ) );
offgraphics.drawLine( x1, y1, x2, y2 );
String lbl = String.valueOf( len );
offgraphics.setColor( stressColor );
offgraphics.drawString( lbl, x1 + ( x2 - x1 ) / 2,
y1 + ( y2 - y1 ) / 2 );
offgraphics.setColor( edgeColor );
}
FontMetrics fm = offgraphics.getFontMetrics();
for( int i = 0; i < nnodes; i++ ) {
paintNode( offgraphics, nodes[i], fm );
}
g.drawImage( offscreen, 0, 0, null );
}
//更新节点边的信息--------------------------------------------
void updateEdges() {
for( int i = 0; i < nnodes; i++ ) { //仅处理Master节点即可
if( nodes[i].mapNode.isMaster() ) {
synchronized (nodes[i].mapNode.getMemberList()){
if( nodes[i].mapNode.getMemberList().getSize() > 1 ) {
addMemberEdge( nodes[i] ); //加入master和其成员的连线
}
}
addGatewayEdge( nodes[i] ); //加入两组gateway之间的连线
}
}
}
void addMemberEdge( Node masterNode ) {
MemberList memList = masterNode.mapNode.getMemberList();
synchronized (memList){
long masterId = masterNode.mapNode.getID();
long memberId;
int x1, y1, x2, y2;
for( int i = 0; i < memList.getSize(); i++ ) { //注意到一个事实:节点的ID号等于它在nodes[]中的位置
memberId = memList.getMbrId( i );
if( memberId != masterNode.mapNode.getID() ) {
if( !edgeExisted( masterId, memberId ) ) {
x1 = ( int )masterNode.mapNode.getPosition().getX();
y1 = ( int )masterNode.mapNode.getPosition().getY();
x2 = ( int )nodes[ ( int )memberId].mapNode.getPosition().
getX();
y2 = ( int )nodes[ ( int )memberId].mapNode.getPosition().
getY();
this.addEdge( String.valueOf( masterId ),
String.valueOf( memberId ),
( int )Math.sqrt( ( x1 - x2 ) * ( x1 - x2 ) +
( y1 - y2 ) * ( y1 - y2 ) ),
Edge.TYPE_MEMBER );
addNeighbourEdge( nodes[ ( int )memberId], masterNode ); //加入成员之间的连线
}
}
}
}
}
void addNeighbourEdge( Node memberNode, Node masterNode ) {
ClientNode mapMemNode = memberNode.mapNode;
ClientNode mapMasterNode = masterNode.mapNode;
//如果等于2就只剩下自己和自己,自己和master两条已经画过的线了
if( mapMemNode.getNeighbourList().getSize() > 2 ) {
NeighbourList nebrTemp = mapMemNode.getNeighbourList();
synchronized ( nebrTemp ){
Object[] nebrData;
for( int i = 0; i < nebrTemp.getSize(); i++ ) {
nebrData = nebrTemp.get( i );
long key = ( ( Long )nebrData[0] ).longValue(),
value = ( ( Long )nebrData[1] ).longValue();
//邻居节点不能是自己和master节点,也不能是gatway节点,
if( ( key != mapMemNode.getID() ) &&
( key != mapMemNode.getMasterId() ) ) { //在这里邻居节点也不能是外组的,当然连接更不可以已经存在
if( value == mapMasterNode.getID() &&
!edgeExisted( mapMemNode.getID(), key ) ) {
int x1 = ( int )mapMemNode.getPosition().getX();
int y1 = ( int )mapMemNode.getPosition().getY();
int x2 = ( int )nodes[ ( int )key].mapNode.
getPosition().
getX();
int y2 = ( int )nodes[ ( int )key].mapNode.
getPosition().
getY();
this.addEdge( String.valueOf( mapMemNode.getID() ),
String.valueOf( key ),
( int )Math.sqrt( ( x1 - x2 ) *
( x1 - x2 ) +
( y1 - y2 ) * ( y1 - y2 ) ),
Edge.TYPE_NEIGHBOUR );
}
}
}
}
}
}
void addGatewayEdge( Node masterNode ) {
ClientNode master = masterNode.mapNode;
for( int i = 0; i < master.getGroupAdjacencyList().getSize(); i++ ) {
synchronized ( master.getGroupAdjacencyList() ){
long[] value = master.getGroupAdjacencyList().get( i );
if( !edgeExisted( value[0], value[1] ) ) {
int x1 = ( int )nodes[ ( int )value[0]].mapNode.getPosition().
getX();
int y1 = ( int )nodes[ ( int )value[0]].mapNode.getPosition().
getY();
int x2 = ( int )nodes[ ( int )value[1]].mapNode.getPosition().
getX();
int y2 = ( int )nodes[ ( int )value[1]].mapNode.getPosition().
getY();
this.addEdge( String.valueOf( value[0] ),
String.valueOf( value[1] ),
( int )Math.sqrt( ( x1 - x2 ) * ( x1 - x2 ) +
( y1 - y2 ) * ( y1 - y2 ) ),
Edge.TYPE_GETWAY );
}
}
}
}
//判断该边是否已经存在
boolean edgeExisted( long from, long to ) {
for( int i = 0; i < nedges; i++ ) {
if( ( ( edges[i].from == from ) && ( edges[i].to == to ) ) ||
( ( edges[i].from == to ) && ( edges[i].to == from ) ) ) {
return true;
}
}
return false;
}
//----------------------------------------
//1.1 mouse event handling-------------------------------------------------
public void mouseClicked( MouseEvent e ) {
}
public void mousePressed( MouseEvent e ) {
if( pick == null ) {
return;
}
double bestdist = Double.MAX_VALUE;
int x = e.getX();
int y = e.getY();
for( int i = 0; i < nnodes; i++ ) {
Node n = nodes[i];
double dist = ( n.x - x ) * ( n.x - x ) + ( n.y - y ) * ( n.y - y );
if( dist < bestdist ) {
pick = n;
bestdist = dist;
}
}
pick.x = x;
pick.y = y;
repaint();
e.consume();
}
public void mouseReleased( MouseEvent e ) {
if( pick == null ) {
return;
}
pick.x = e.getX();
pick.y = e.getY();
//TODO:进行节点位置的更新
repaint();
e.consume();
}
public void mouseEntered( MouseEvent e ) {
}
public void mouseExited( MouseEvent e ) {
}
public void mouseDragged( MouseEvent e ) {
if( pick == null ) {
return;
}
pick.x = e.getX();
pick.y = e.getY();
//TODO:进行节点位置的更新
repaint();
e.consume();
}
public void mouseMoved( MouseEvent e ) {
setToolTipText( "X:" + e.getX() + " Y:" + e.getY() );
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -