package dell_map; // ¶¨Òå°üÃû
|
import javax.swing.*; // µ¼ÈëSwing×é¼þ
|
import javax.swing.event.InternalFrameEvent; // µ¼ÈëÄÚ²¿¿ò¼Üʼþ
|
import javax.swing.event.InternalFrameListener; // µ¼ÈëÄÚ²¿¿ò¼Ü¼àÌýÆ÷
|
import java.awt.*; // µ¼ÈëAWT×é¼þ
|
import java.awt.event.*; // µ¼ÈëAWTʼþ
|
import java.lang.ref.SoftReference; // µ¼ÈëÈíÒýÓÃ
|
import java.util.List; // µ¼ÈëÁбí
|
import java.util.ResourceBundle; // µ¼Èë¹ú¼Ê»¯×ÊÔ´°ü
|
|
import targets.Mapdata; // µ¼ÈëµØÍ¼Êý¾ÝÀà
|
|
public class MapViewer extends JInternalFrame implements Runnable { // µØÍ¼²é¿´Æ÷À࣬¼Ì³ÐÄÚ²¿¿ò¼Ü²¢ÊµÏÖÏß³Ì
|
|
private static final long serialVersionUID = 1L; // ÐòÁл¯°æ±¾ID
|
private MapCanvas canvas; // µØÍ¼»²¼
|
private double scale = 1.0; // Ëõ·Å±ÈÀý
|
private int scaleStep = 200; // Ëõ·Å²½³¤£¨Î´Ê¹Óã©
|
private Point dragOrigin; // ÍÏ×§Æðʼµã
|
private int offsetX = 0; // XÖáÆ«ÒÆÁ¿
|
private int offsetY = 0; // YÖáÆ«ÒÆÁ¿
|
private int canvasWidth; // »²¼¿í¶È
|
private int canvasHeight; // »²¼¸ß¶È
|
private int mapWidth; // µØÍ¼Ôʼ¿í¶È
|
private int mapHeight; // µØÍ¼Ôʼ¸ß¶È
|
private int scaledWidth; // Ëõ·Åºó¿í¶È
|
private int scaledHeight; // Ëõ·Åºó¸ß¶È
|
private double xRatio; // XÖáÏñËØÓëʵ¼Ê¾àÀë±ÈÀý
|
private double yRatio; // YÖáÏñËØÓëʵ¼Ê¾àÀë±ÈÀý
|
private double actualWidth; // µØÍ¼Êµ¼Ê¿í¶È£¨µ¥Î»£ºÀåÃ×£©
|
private double actualHeight; // µØÍ¼Êµ¼Ê¸ß¶È£¨µ¥Î»£ºÀåÃ×£©
|
private Mapdata mapData; // µØÍ¼Êý¾Ý¶ÔÏó
|
private int originX; // ÔµãX×ø±ê£¨ÏñËØ£©
|
private int originY; // ÔµãY×ø±ê£¨ÏñËØ£©
|
private SoftReference<Image> mapImageRef; // µØÍ¼Í¼ÏñµÄÈíÒýÓÃ
|
private boolean isOpen = false; // ´°¿ÚÊÇ·ñ´ò¿ª±êÖ¾
|
private int sleepTime = 300; // ÖØ»æÏß³ÌÐÝÃßʱ¼ä£¨ºÁÃ룩
|
private Point mousePosition = new Point(0, 0); // ´æ´¢Êó±êλÖÃ
|
private ResourceBundle messages; // ¹ú¼Ê»¯×ÊÔ´°ü
|
|
public MapViewer(Mapdata mapData, ResourceBundle messages) { // ¹¹Ô캯Êý
|
super(mapData.getMapName(), // ´°¿Ú±êÌâ
|
true, // ¿É¹Ø±Õ
|
true, // ¿É×î´ó»¯
|
true, // ¿É×îС»¯
|
true); // ¿Éµ÷Õû´óС
|
this.mapData = mapData; // ³õʼ»¯µØÍ¼Êý¾Ý
|
this.messages = messages; // ³õʼ»¯×ÊÔ´°ü
|
initialize(); // µ÷Óóõʼ»¯·½·¨
|
}
|
|
public static void createMapViewer(JDesktopPane desktopPane, String mapName, ResourceBundle messages) { // ´´½¨µØÍ¼²é¿´Æ÷¾²Ì¬·½·¨
|
// ¸ù¾ÝÃû³Æ»ñÈ¡µØÍ¼Êý¾Ý
|
Mapdata mapData = Dell_Map.getMapByName(mapName); // »ñÈ¡µØÍ¼Êý¾Ý
|
if (mapData == null) { // Èç¹ûµØÍ¼²»´æÔÚ
|
String errorMsg = messages.getString("MAP_NOT_FOUND"); // »ñÈ¡´íÎóÏûÏ¢
|
JOptionPane.showMessageDialog(desktopPane, errorMsg.replace("{0}", mapName), // ÏÔʾ´íÎó¶Ô»°¿ò
|
messages.getString("ERROR"), JOptionPane.ERROR_MESSAGE);
|
return; // ·µ»Ø
|
}
|
|
MapViewer viewer = new MapViewer(mapData, messages); // ´´½¨µØÍ¼²é¿´Æ÷ʵÀý
|
viewer.setVisible(true); // ÉèÖô°¿Ú¿É¼û
|
|
// Ëæ»úÉèÖô°¿ÚλÖÃ
|
int x = (int)(Math.random() * (desktopPane.getWidth() - viewer.getWidth())); // Ëæ»úX×ø±ê
|
int y = (int)(Math.random() * (desktopPane.getHeight() - viewer.getHeight())); // Ëæ»úY×ø±ê
|
viewer.setLocation(x, y); // ÉèÖô°¿ÚλÖÃ
|
|
desktopPane.add(viewer); // Ìí¼Ó´°¿Úµ½×À̾̾°å
|
viewer.toFront(); // ´°¿ÚÖö¥
|
}
|
|
private void initialize() { // ³õʼ»¯·½·¨
|
// ÉèÖô°¿Ú´óС
|
setSize(800, 600); // ÉèÖóõʼ´óС
|
setDefaultCloseOperation(HIDE_ON_CLOSE); // ÉèÖùرղÙ×÷ΪÒþ²Ø
|
setBorder(null); // È¥µô´°Ìå±ß¿ò
|
|
// ¼ÓÔØµØÍ¼Í¼Ïñ
|
String mapPath = "systemfile/imagemap/" + mapData.getMapNameDetaile(); // µØÍ¼Â·¾¶
|
Image image = new ImageIcon(mapPath).getImage(); // ¼ÓÔØÍ¼Ïñ
|
mapImageRef = new SoftReference<>(image); // ´´½¨ÈíÒýÓÃ
|
|
// »ñÈ¡µØÍ¼³ß´ç
|
mapWidth = image.getWidth(null); // »ñÈ¡Ôʼ¿í¶È
|
mapHeight = image.getHeight(null); // »ñÈ¡Ôʼ¸ß¶È
|
scaledWidth = mapWidth; // ³õʼ»¯Ëõ·Å¿í¶È
|
scaledHeight = mapHeight; // ³õʼ»¯Ëõ·Å¸ß¶È
|
|
// »ñÈ¡µØÍ¼²ÎÊý
|
actualWidth = Double.parseDouble(mapData.getActualXLength()); // ʵ¼Ê¿í¶È£¨ÀåÃ×£©
|
actualHeight = Double.parseDouble(mapData.getActualYLength()); // ʵ¼Ê¸ß¶È£¨ÀåÃ×£©
|
originX = Integer.parseInt(mapData.getX0Coordinate()); // ÔµãX×ø±ê
|
originY = Integer.parseInt(mapData.getY0Coordinate()); // ÔµãY×ø±ê
|
|
// ¼ÆËã±ÈÀý
|
xRatio = actualWidth / scaledWidth; // ¼ÆËãXÖá±ÈÀý£¨ÀåÃ×/ÏñËØ£©
|
yRatio = actualHeight / scaledHeight; // ¼ÆËãYÖá±ÈÀý£¨ÀåÃ×/ÏñËØ£©
|
|
// ÉèÖÃÄÚÈÝÃæ°å
|
Container content = getContentPane(); // »ñÈ¡ÄÚÈÝÃæ°å
|
content.setLayout(new BorderLayout()); // ÉèÖñ߽粼¾Ö
|
content.setBackground(Color.WHITE); // ÉèÖñ³¾°É«
|
|
// ´´½¨»²¼
|
canvas = new MapCanvas(); // ʵÀý»¯»²¼
|
content.add(canvas, BorderLayout.CENTER); // Ìí¼Óµ½ÖÐÐÄ
|
|
// ÉèÖô°¿Úͼ±ê
|
setFrameIcon(new ImageIcon("image/icon/mapicon.png")); // ÉèÖÃͼ±ê
|
|
// Ìí¼Ó´°¿Úʼþ¼àÌýÆ÷
|
addInternalFrameListener(new InternalFrameListener() { // Ìí¼ÓÄÚ²¿¿ò¼Ü¼àÌýÆ÷
|
@Override
|
public void internalFrameOpened(InternalFrameEvent e) { // ´°¿Ú´ò¿ªÊ±
|
startThread(); // Æô¶¯ÖØ»æÏß³Ì
|
}
|
|
@Override
|
public void internalFrameClosing(InternalFrameEvent e) { // ´°¿Ú¹Ø±Õʱ
|
isOpen = false; // ÉèÖùرձêÖ¾
|
mapImageRef.clear(); // Çå³ýͼÏñÒýÓÃ
|
}
|
|
@Override public void internalFrameClosed(InternalFrameEvent e) {} // ´°¿Ú¹Ø±Õºó£¨¿ÕʵÏÖ£©
|
@Override public void internalFrameIconified(InternalFrameEvent e) { // ´°¿Ú×îС»¯Ê±
|
isOpen = false; // Í£Ö¹ÖØ»æÏß³Ì
|
}
|
@Override public void internalFrameDeiconified(InternalFrameEvent e) { // ´°¿Ú»Ö¸´Ê±
|
startThread(); // Æô¶¯ÖØ»æÏß³Ì
|
}
|
@Override public void internalFrameActivated(InternalFrameEvent e) {} // ´°¿Ú¼¤»îʱ£¨¿ÕʵÏÖ£©
|
@Override public void internalFrameDeactivated(InternalFrameEvent e) {} // ´°¿Úʧ»îʱ£¨¿ÕʵÏÖ£©
|
});
|
}
|
|
public void startThread() { // Æô¶¯Ï̷߳½·¨
|
if (!isOpen) { // Èç¹ûÏß³ÌδÔËÐÐ
|
isOpen = true; // ÉèÖÃÔËÐбêÖ¾
|
new Thread(this).start(); // Æô¶¯ÐÂÏß³Ì
|
}
|
}
|
|
@Override
|
public void run() { // Ïß³ÌÔËÐз½·¨
|
while (isOpen) { // Ñ»·Ö±µ½¹Ø±Õ
|
try {
|
canvas.repaint(); // ÖØ»æ»²¼
|
Thread.sleep(sleepTime); // Ïß³ÌÐÝÃß
|
} catch (InterruptedException e) {
|
e.printStackTrace(); // ´òÓ¡Òì³£
|
}
|
}
|
}
|
|
/**
|
* µØÍ¼»²¼Àà
|
*/
|
class MapCanvas extends Canvas implements MouseListener, MouseMotionListener, MouseWheelListener { // ×Ô¶¨Ò廲¼Àà
|
|
private static final long serialVersionUID = 1L; // ÐòÁл¯°æ±¾ID
|
private Image buffer; // Ë«»º³åͼÏñ
|
|
public MapCanvas() { // ¹¹Ô캯Êý
|
dragOrigin = new Point(); // ³õʼ»¯ÍÏ×§Æðµã
|
addMouseListener(this); // Ìí¼ÓÊó±ê¼àÌýÆ÷
|
addMouseMotionListener(this); // Ìí¼ÓÊó±êÒÆ¶¯¼àÌýÆ÷
|
addMouseWheelListener(this); // Ìí¼ÓÊó±ê¹öÂÖ¼àÌýÆ÷
|
setBackground(Color.WHITE); // ÉèÖñ³¾°É«
|
setBorder(null); // È¥µô»²¼±ß¿ò
|
}
|
|
// Ë«»º³å½â¾öÉÁ˸ÎÊÌâ
|
@Override
|
public void update(Graphics g) { // ÖØÐ´updateʵÏÖË«»º³å
|
if (buffer == null || // Èç¹û»º³åͼÏñ²»´æÔÚ
|
buffer.getWidth(null) != getWidth() || // »ò³ß´ç²»Æ¥Åä
|
buffer.getHeight(null) != getHeight()) {
|
buffer = createImage(getWidth(), getHeight()); // ´´½¨Ð»º³åͼÏñ
|
}
|
|
if (buffer != null) { // Èç¹û»º³åͼÏñÓÐЧ
|
Graphics bg = buffer.getGraphics(); // »ñÈ¡»º³åͼÐζÔÏó
|
bg.setColor(getBackground()); // ÉèÖñ³¾°É«
|
bg.fillRect(0, 0, getWidth(), getHeight()); // Ìî³ä±³¾°
|
paint(bg); // ÔÚ»º³åÉÏ»æÖÆÄÚÈÝ
|
g.drawImage(buffer, 0, 0, this); // ½«»º³å»æÖƵ½ÆÁÄ»
|
} else {
|
super.update(g); // µ÷Óø¸Àà·½·¨
|
}
|
}
|
|
@Override
|
public void paint(Graphics g) { // »æÖÆ·½·¨
|
super.paint(g); // µ÷Óø¸Àà
|
Graphics2D g2d = (Graphics2D) g; // ת»»ÎªGraphics2D
|
|
// ÉèÖÿ¹¾â³Ý
|
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
|
RenderingHints.VALUE_ANTIALIAS_ON); // ¿ªÆôͼÐο¹¾â³Ý
|
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
|
RenderingHints.VALUE_TEXT_ANTIALIAS_ON); // ¿ªÆôÎı¾¿¹¾â³Ý
|
|
// »ñÈ¡µ±Ç°»²¼³ß´ç
|
canvasWidth = getWidth(); // »ñÈ¡»²¼¿í¶È
|
canvasHeight = getHeight(); // »ñÈ¡»²¼¸ß¶È
|
|
// »æÖƵØÍ¼
|
Image mapImage = mapImageRef.get(); // »ñÈ¡µØÍ¼Í¼Ïñ
|
if (mapImage != null) { // Èç¹ûͼÏñ´æÔÚ
|
g2d.drawImage(mapImage, offsetX, offsetY, scaledWidth, scaledHeight, this); // »æÖƵØÍ¼
|
}
|
|
// »æÖÆ×ø±êÔµã
|
drawOrigin(g2d); // µ÷ÓÃÔµã»æÖÆ·½·¨
|
|
// ÔÚÓÒϽÇÏÔʾ±ÈÀýÐÅÏ¢
|
drawMapInfo(g2d); // µ÷ÓõØÍ¼ÐÅÏ¢»æÖÆ·½·¨
|
|
// ÔÚ×óϽÇÏÔʾÊó±êλÖõÄʵ¼Ê×ø±ê
|
drawMouseCoordinates(g2d); // µ÷ÓÃÊó±ê×ø±ê»æÖÆ·½·¨
|
}
|
|
private void drawOrigin(Graphics2D g2d) { // »æÖÆÔµã·½·¨
|
int originScreenX = offsetX - (int)(originX / xRatio); // ¼ÆËãÔµãÆÁÄ»X×ø±ê
|
int originScreenY = offsetY - (int)(originY / yRatio); // ¼ÆËãÔµãÆÁÄ»Y×ø±ê
|
g2d.setColor(Color.RED); // ÉèÖúìÉ«
|
g2d.fillOval(originScreenX - 5, originScreenY - 5, 10, 10); // »æÖÆÔµã±ê¼Ç
|
g2d.setColor(Color.BLACK); // ÉèÖúÚÉ«
|
// ʹÓÃ×ÊÔ´°ü»ñȡԵã±ê¼ÇÎı¾
|
g2d.drawString(messages.getString("ORIGIN_MARK"), originScreenX + 10, originScreenY); // »æÖÆÔµã±êÇ©
|
}
|
|
private void drawMapInfo(Graphics2D g2d) { // »æÖƵØÍ¼ÐÅÏ¢·½·¨
|
g2d.setColor(Color.BLACK); // ÉèÖúÚÉ«
|
Font font = new Font("΢ÈíÑźÚ", Font.BOLD, 14); // ´´½¨×ÖÌå
|
g2d.setFont(font); // ÉèÖÃ×ÖÌå
|
|
// ʹÓÃ×ÊÔ´°ü»ñÈ¡±ÈÀýÎı¾
|
String scaleText = String.format(messages.getString("SCALE_FORMAT"), scale); // ¸ñʽ»¯±ÈÀýÎı¾
|
FontMetrics fm = g2d.getFontMetrics(); // »ñÈ¡×ÖÌå¶ÈÁ¿
|
int textWidth = fm.stringWidth(scaleText); // ¼ÆËãÎı¾¿í¶È
|
|
// ÔÚÓÒϽǻæÖƱÈÀýÐÅÏ¢
|
int x = canvasWidth - textWidth - 20; // ¼ÆËãX×ø±ê
|
int y = canvasHeight - 20; // ¼ÆËãY×ø±ê
|
|
g2d.drawString(scaleText, x, y); // »æÖÆÎı¾
|
}
|
|
private void drawMouseCoordinates(Graphics2D g2d) { // »æÖÆÊó±ê×ø±ê·½·¨
|
// ¼ÆËãÊó±êλÖõÄʵ¼Ê×ø±ê£¨ÀåÃ×£©
|
double actualX = originX + (mousePosition.x - offsetX) * xRatio; // ¼ÆËãʵ¼ÊX×ø±ê
|
double actualY = originY + (mousePosition.y - offsetY) * yRatio; // ¼ÆËãʵ¼ÊY×ø±ê
|
|
g2d.setColor(Color.BLACK); // ÉèÖúÚÉ«
|
Font font = new Font("΢ÈíÑźÚ", Font.BOLD, 14); // ´´½¨×ÖÌå
|
g2d.setFont(font); // ÉèÖÃ×ÖÌå
|
|
// ʹÓÃ×ÊÔ´°ü»ñÈ¡×ø±êÎı¾
|
String coordText = String.format( // ¸ñʽ»¯×ø±êÎı¾
|
messages.getString("COORDINATE_FORMAT"),
|
actualX,
|
actualY
|
);
|
|
// ÔÚ×óϽǻæÖÆ×ø±êÐÅÏ¢
|
int x = 20; // X×ø±ê
|
int y = canvasHeight - 20; // Y×ø±ê
|
|
g2d.drawString(coordText, x, y); // »æÖÆÎı¾
|
}
|
|
// Êó±êʼþ´¦Àí
|
@Override
|
public void mousePressed(MouseEvent e) { // Êó±ê°´ÏÂ
|
dragOrigin = e.getPoint(); // ¼Ç¼ÍÏ×§Æðµã
|
setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR)); // ÉèÖÃÒÆ¶¯¹â±ê
|
}
|
|
@Override
|
public void mouseDragged(MouseEvent e) { // Êó±êÍÏ×§
|
Point current = e.getPoint(); // »ñÈ¡µ±Ç°µã
|
offsetX += current.x - dragOrigin.x; // ¸üÐÂXÆ«ÒÆ
|
offsetY += current.y - dragOrigin.y; // ¸üÐÂYÆ«ÒÆ
|
dragOrigin = current; // ¸üÐÂÍÏ×§Æðµã
|
repaint(); // ÖØ»æ»²¼
|
}
|
|
@Override
|
public void mouseReleased(MouseEvent e) { // Êó±êÊÍ·Å
|
setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); // »Ö¸´Ä¬ÈϹâ±ê
|
}
|
|
@Override
|
public void mouseMoved(MouseEvent e) { // Êó±êÒÆ¶¯
|
// ¸üÐÂÊó±êλÖÃ
|
mousePosition = e.getPoint(); // ¼Ç¼Êó±êλÖÃ
|
repaint(); // ÖØ»æ»²¼
|
}
|
|
@Override
|
public void mouseWheelMoved(MouseWheelEvent e) { // Êó±ê¹öÂÖʼþ
|
int rotation = e.getWheelRotation(); // »ñÈ¡¹öÂÖÐýת·½Ïò
|
double zoomFactor = 1.1; // Ëõ·ÅÒò×Ó
|
|
// ¼ÆËãÊó±êµ±Ç°Î»ÖöÔÓ¦µÄµØÍ¼×ø±ê
|
Point mousePos = e.getPoint(); // »ñÈ¡Êó±êλÖÃ
|
double prevMapX = (mousePos.x - offsetX) * xRatio; // ¼ÆËãÔµØÍ¼X×ø±ê
|
double prevMapY = (mousePos.y - offsetY) * yRatio; // ¼ÆËãÔµØÍ¼Y×ø±ê
|
|
// µ÷ÕûËõ·Å±ÈÀý£¨ÏÞÖÆÔÚ0.2-5.0±¶Ö®¼ä£©
|
if (rotation < 0 && scale < 5.0) { // ·Å´ó
|
scale *= zoomFactor; // ·Å´ó±ÈÀý
|
if (scale > 5.0) { // ÉÏÏÞ¼ì²é
|
scale = 5.0; // ÉèÖÃ×î´óÖµ
|
}
|
} else if (rotation > 0 && scale > 0.2) { // ËõС
|
scale /= zoomFactor; // ËõС±ÈÀý
|
if (scale < 0.2) { // ÏÂÏÞ¼ì²é
|
scale = 0.2; // ÉèÖÃ×îСֵ
|
}
|
}
|
|
// Ó¦ÓÃËõ·Å
|
scaledWidth = (int)(mapWidth * scale); // ¼ÆËãпí¶È
|
scaledHeight = (int)(mapHeight * scale); // ¼ÆËãи߶È
|
|
// ¸üбÈÀý
|
xRatio = actualWidth / scaledWidth; // ¸üÐÂX±ÈÀý
|
yRatio = actualHeight / scaledHeight; // ¸üÐÂY±ÈÀý
|
|
// ¼ÆËãËõ·ÅºóµÄÆ«ÒÆÁ¿£¬Ê¹Êó±êλÖöÔÓ¦µÄµØÍ¼Î»Öñ£³Ö²»±ä
|
double newMapX = prevMapX / xRatio; // ¼ÆËãÐÂÆÁÄ»X×ø±ê
|
double newMapY = prevMapY / yRatio; // ¼ÆËãÐÂÆÁÄ»Y×ø±ê
|
offsetX = (int)(mousePos.x - newMapX); // ¸üÐÂXÆ«ÒÆ
|
offsetY = (int)(mousePos.y - newMapY); // ¸üÐÂYÆ«ÒÆ
|
|
repaint(); // ÖØ»æ»²¼
|
}
|
|
// ÆäËûÊó±êʼþ£¨¿ÕʵÏÖ£©
|
@Override public void mouseClicked(MouseEvent e) {} // Êó±êµã»÷
|
@Override public void mouseEntered(MouseEvent e) {} // Êó±ê½øÈë
|
@Override public void mouseExited(MouseEvent e) {} // Êó±êÀ뿪
|
}
|
|
/**
|
* ´´½¨ËùÓеØÍ¼µÄ´°¿Ú
|
*/
|
public static void createAllMapViewers(JDesktopPane desktopPane, ResourceBundle messages) { // ´´½¨ËùÓеØÍ¼´°¿Ú
|
List<Mapdata> allMaps = Dell_Map.getAllMaps(); // »ñÈ¡ËùÓеØÍ¼Êý¾Ý
|
for (Mapdata map : allMaps) { // ±éÀúµØÍ¼
|
MapViewer viewer = new MapViewer(map, messages); // ´´½¨²é¿´Æ÷
|
viewer.setVisible(true); // ÉèÖÿɼû
|
|
// Ëæ»úÉèÖô°¿ÚλÖÃ
|
int x = (int)(Math.random() * (desktopPane.getWidth() - viewer.getWidth())); // Ëæ»úX
|
int y = (int)(Math.random() * (desktopPane.getHeight() - viewer.getHeight())); // Ëæ»úY
|
viewer.setLocation(x, y); // ÉèÖÃλÖÃ
|
|
desktopPane.add(viewer); // Ìí¼Óµ½×ÀÃæ
|
viewer.toFront(); // Öö¥
|
}
|
}
|
}
|