我们正在开展一个学校项目,我们使用JavaFX在画布上绘制一个非常详细的地图,并通过JFXPanel集成Swing。每次打开应用程序时,画布都是黑色的,直到调整大小或与画布进行任何交互,例如平移或缩放。我已经通过整个互联网搜索错误,但不幸的是没有运气。
代码段:
public class CanvasViewNew extends Application {
private AnchorPane rootLayout;
private Stage primaryStage;
private Canvas canvas;
@Override
public void start(Stage primaryStage) {
this.primaryStage = primaryStage;
Model model = new Model("Data/Data/cph.zip");
canvas = new Canvas(model);
new MouseController(canvas, model);
SwingNode swingNode = new SwingNode();
rootLayout = new AnchorPane();
createSwingContent(swingNode);
//Sets canvas to a prefered size.
canvas.setPreferredSize(new Dimension(1000, 1000));
//Creates and sets the scene to an AnchorPane.
Scene scene = new Scene(rootLayout);
//Adds the swingnode to the RootLayout.
rootLayout.getChildren().addAll(swingNode);
System.out.println(swingNode.getScene());
primaryStage.setScene(scene);
primaryStage.show();
rootLayout.requestFocus();
swingNode.requestFocus();
swingNode.autosize();
swingNode.resize(1000,1000);
//Calls the panning and zoom methods in canvas, which enables the zooming and panning on canvas.
canvas.pan(-model.getMinLon(), -model.getMaxLat());
canvas.zoom((primaryStage.getWidth()) + 200 / (model.getMaxLon() - model.getMinLon()), 0, 0);
canvas.zoomFactor = primaryStage.getWidth() / (model.getMaxLon() - model.getMinLon());
canvas.minZoom = canvas.zoomFactor / 4;
canvas.maxZoom = canvas.zoomFactor * 200;
}
private void createSwingContent(SwingNode swingNode) {
SwingUtilities.invokeLater(() -> {
// AnchorPane canvasPane = adjustSwingNode(swingNode);
swingNode.setContent(canvas);
});
}
public static void main(String args[]) {
launch(args);
}
public class Canvas extends JFXPanel implements Observer {
private final Model model;
private boolean useAntiAliasing = false;
private AffineTransform transform = new AffineTransform();
private boolean drawingModeEnabled = false;
private final String drawingModeMessage = "Drawing Mode enabled";
private double fps = 0.0;
private KDTree.Rect searchRect;
private KDTreePath.Rect searchRectway;
private DrawTreeSplits splits;
public double maxZoom;
public double minZoom;
public double zoomFactor;
public Canvas(Model m) {
this.model = m;
model.addObserver(this);
splits = new DrawTreeSplits(model.getWayTree(), model.getMinLon(), model.getMaxLon(), model.getMinLat(), model.getMaxLat());
repaint();
}
@Override
public void paint(Graphics _g) {
long t1 = System.nanoTime();
Graphics2D g = (Graphics2D) _g;
g.setStroke(new BasicStroke(Float.MIN_VALUE));
if (drawingModeEnabled) {
int width = g.getFontMetrics().stringWidth(drawingModeMessage);
int height = g.getFontMetrics().getHeight();
// draw string in red, reset to black afterwards.
g.setPaint(Color.red);
g.drawString(drawingModeMessage, getWidth() - width - 20, getHeight() - height - 10);
g.setPaint(Color.black);
}
Rectangle2D viewRect = new Rectangle2D.Double(0, 0, getWidth(), getHeight());
//Draw methods
g.setBackground(new Color(152, 152, 152));
g.setPaint(new Color(60, 149, 255));
g.fill(viewRect);
g.transform(transform);
try {
viewRect = transform.createInverse().createTransformedShape(viewRect).getBounds2D();
} catch (NoninvertibleTransformException e) {
e.printStackTrace();
}
if (useAntiAliasing) {
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
}
//draw split lines for FUN
//draw Coastlines
g.setPaint(new Color(237, 237, 237));
for (Shape coastline : model.get(OSMWayType.COASTLINE)) {
if (coastline.intersects(viewRect)) {
g.fill(coastline);
}
}
//draw unknown lines
/* g.setStroke(new BasicStroke(0.00001f));
g.setPaint(new Color(0, 0, 0));
for (Shape line : model.get(OSMWayType.UNKNOWN)) {
if (line.intersects(viewRect)) {
g.draw(line);
}
}*/
searchRect = new KDTree.Rect(viewRect.getMinX(), viewRect.getMinY(), viewRect.getMaxX(), viewRect.getMaxY());
searchRectway = new KDTreePath.Rect(viewRect.getMinX(), viewRect.getMinY(), viewRect.getMaxX(), viewRect.getMaxY());
if (zoomFactor > 2300)
drawLandScapes(g);
if (zoomFactor > 5000)
drawOutlines(g);
if (zoomFactor > 10000) {
drawStructures(g);
drawCityDetails(g);
}
if (zoomFactor > 7500)
drawCityRoads(g);
if (zoomFactor > 28000)
drawCitySmallDetails(g);
if (zoomFactor > 100)
drawMainRoads(g);
if (zoomFactor > 15000)
drawCitySmallRoads(g);
if (zoomFactor > 35000)
drawPoints(g);
//splits.paint(g);
long t2 = System.nanoTime();
fps = (fps + 1e9 / (t2 - t1)) / 2;
g.setTransform(new AffineTransform());
g.setColor(Color.WHITE);
g.fillRect(5, 5, 80, 20);
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);
g.setColor(Color.BLACK);
g.drawRect(5, 5, 80, 20);
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g.drawString(String.format("FPS: %.1f", fps), 10, 20);
}
private void drawMainRoads(Graphics2D g) {
for (OSMWayPath shape : model.getHighWayTree().rangeSearch(searchRectway)) {
//draw Highways
if (shape.getType() == OSMWayType.HIGHWAY) {
g.setStroke(new BasicStroke(0.00005f));
g.setPaint(new Color(182, 63, 61));
g.draw(shape);
}
//draw secondary highways
if (shape.getType() == OSMWayType.SECONDARYHIGHWAY) {
g.setStroke(new BasicStroke(0.0002f));
g.setPaint(new Color(214, 183, 25));
g.draw(shape);
}
//draw tertiary roads
if (shape.getType() == OSMWayType.TERTIARY && zoomFactor > 400) {
g.setStroke(new BasicStroke(0.0002f));
g.setPaint(new Color(0, 255, 122));
g.draw(shape);
}
}
}
private void drawOutlines(Graphics2D g) {
for (OSMWayPath shape : model.getWayTree().rangeSearch(searchRectway)) {
//draw residential area
if (shape.getType() == OSMWayType.RESIDENTIALAREA) {
g.setPaint(new Color(115, 115, 121));
g.fill(shape);
}
//draw industrial area
if (shape.getType() == OSMWayType.INDUSTRIALAREA) {
g.setPaint(new Color(95, 94, 95));
g.fill(shape);
}
}
}
private void drawLandScapes(Graphics2D g) {
for (OSMWayPath shape : model.getWayTree().rangeSearch(searchRectway)) {
//draw water
if (shape.getType() == OSMWayType.WATER) {
g.setPaint(new Color(60, 149, 255));
g.fill(shape);
}
//draw forests
if (shape.getType() == OSMWayType.FOREST) {
g.setPaint(new Color(0, 102, 2));
g.fill(shape);
}
//draw beaches
if (shape.getType() == OSMWayType.BEACH) {
g.setPaint(new Color(194, 178, 128));
g.fill(shape);
}
//draw grass
if (shape.getType() == OSMWayType.GRASS) {
g.setPaint(new Color(0, 249, 2));
g.fill(shape);
}
//draw sand areas
if (shape.getType() == OSMWayType.SAND) {
g.setPaint(new Color(194, 178, 128));
g.fill(shape);
}
//draw nature reserves
if (shape.getType() == OSMWayType.NATURERESERVE) {
g.setPaint(new Color(0, 203, 2));
g.fill(shape);
}
//draw woods
if (shape.getType() == OSMWayType.WOOD) {
g.setPaint(new Color(0, 156, 2));
g.fill(shape);
}
//draw waterways
if (shape.getType() == OSMWayType.WATERWAY) {
g.setStroke(new BasicStroke(0.00004f));
g.setPaint(new Color(60, 149, 255));
g.draw(shape);
}
//draw golf courses
if (shape.getType() == OSMWayType.GOLF) {
g.setPaint(new Color(78, 156, 0));
g.fill(shape);
}
}
}
private void drawPoints(Graphics2D g) {
//draw points
for (OSMPoint point : model.getPointTree().rangeSearch(searchRect)) {
g.setPaint(new Color(0, 11, 255));
if (point.getType() == OSMNodeType.STATION) {
Rectangle2D.Double rect = new Rectangle2D.Double(point.getX(), point.getY(), 0.00010, 0.00010);
g.fill(rect);
}
// draw cafes as points
if (point.getType() == OSMNodeType.CAFE) {
g.setPaint(new Color(211, 104, 16));
Ellipse2D.Double cafe = new Ellipse2D.Double(point.getX(), point.getY(), 0.00004, 0.00004);
g.fill(cafe);
}
//draw shops as points
if (point.getType() == OSMNodeType.SHOP) {
g.setPaint(new Color(31, 211, 17));
Ellipse2D.Double shop = new Ellipse2D.Double(point.getX(), point.getY(), 0.00004, 0.00004);
g.fill(shop);
}
//draw shops as points
if (point.getType() == OSMNodeType.EATINGPLACE) {
g.setPaint(new Color(47, 211, 210));
Ellipse2D.Double eat = new Ellipse2D.Double(point.getX(), point.getY(), 0.00004, 0.00004);
g.fill(eat);
}
}
}
private void drawCityRoads(Graphics2D g) {
for (OSMWayPath shape : model.getWayTree().rangeSearch(searchRectway)) {
if (shape.getType() == OSMWayType.RESIDENTIAL) {
g.setStroke(new BasicStroke(0.00002f));
g.setPaint(new Color(255, 255, 255));
g.draw(shape);
}
//draw railroad
if (shape.getType() == OSMWayType.RAIL) {
g.setStroke(new BasicStroke(0.00003f));
g.setPaint(new Color(198, 228, 26));
g.draw(shape);
}
}
}
private void drawCitySmallRoads(Graphics2D g) {
for (OSMWayPath shape : model.getWayTree().rangeSearch(searchRectway)) {
//draw normal roads
if (shape.getType() == OSMWayType.ROAD) {
g.setStroke(new BasicStroke(0.00003f));
g.setPaint(new Color(255, 255, 255));
g.draw(shape);
}
//draw metro lines
if (shape.getType() == OSMWayType.METRO) {
//g.setStroke(new BasicStroke(0.00005f, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_BEVEL, 0.00007f, new float[]{0.00012f}, 0.0005f));
g.setStroke(new BasicStroke(0.00005f));
g.setPaint(new Color(194, 0, 7));
g.draw(shape);
}
//draw bike roads
if (shape.getType() == OSMWayType.BIKE) {
//g.setStroke(new BasicStroke(0.00002f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND, 0.00002f, new float[]{0.00003f}, 0f));
g.setStroke(new BasicStroke(0.00001f));
g.setPaint(new Color(19, 75, 214));
g.draw(shape);
}
//draw footway roads
if (shape.getType() == OSMWayType.FOOTWAY) {
//g.setStroke(new BasicStroke(0.00001f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND, 0.00003f, new float[]{0.00003f}, 0f));
g.setStroke(new BasicStroke(0.00001f));
g.setPaint(new Color(214, 48, 46));
g.draw(shape);
}
//draw paths
if (shape.getType() == OSMWayType.PATH) {
g.setStroke(new BasicStroke(0.00001f));
g.setPaint(new Color(214, 48, 46));
g.draw(shape);
}
}
}
private void drawCityDetails(Graphics2D g) {
for (OSMWayPath shape : model.getCityDetailsTree().rangeSearch(searchRectway)) {
//draw allotments
if (shape.getType() == OSMWayType.ALLOTMENTS) {
g.setPaint(new Color(141, 195, 30));
g.fill(shape);
}
//draw parks
if (shape.getType() == OSMWayType.PARK) {
g.setPaint(new Color(29, 195, 0));
g.fill(shape);
}
//draw gardens
if (shape.getType() == OSMWayType.GARDEN) {
g.setPaint(new Color(117, 195, 16));
g.fill(shape);
}
//draw parkingLots
if (shape.getType() == OSMWayType.PARKING) {
g.setPaint(new Color(55, 70, 132));
g.fill(shape);
}
}
}
private void drawCitySmallDetails(Graphics2D g) {
for (OSMWayPath shape : model.getCityDetailsTree().rangeSearch(searchRectway)) {
//draw pitches (sporting area)
if (shape.getType() == OSMWayType.PITCH) {
g.setPaint(new Color(138, 169, 182));
g.fill(shape);
}
//draw Piers
if (shape.getType() == OSMWayType.PIER) {
g.setPaint(new Color(147, 80, 25));
g.fill(shape);
}
//draw Piers
if (shape.getType() == OSMWayType.PLAYGROUND) {
g.setPaint(new Color(203, 123, 10));
g.fill(shape);
}
}
}
private void drawStructures(Graphics2D g) {
//draw buildings
g.setStroke(new BasicStroke(0.00001f));
for (OSMWayPath shape : model.getWayTree().rangeSearch(searchRectway)) {
if (shape.getType() == OSMWayType.BUILDING) {
g.setPaint(new Color(144, 144, 150));
g.fill(shape);
}
//draw bridges
if (shape.getType() == OSMWayType.BRIDGE) {
g.setPaint(new Color(146, 142, 149));
g.fill(shape);
}
}
}
/**
* This method is called whenever the observed object is changed. An
* application calls an <tt>Observable</tt> object's
* <code>notifyObservers</code> method to have all the object's
* observers notified of the change.
*
* @param o the observable object.
* @param arg an argument passed to the <code>notifyObservers</code>
*/
@Override
public void update(Observable o, Object arg) {
repaint();
}
public void toggleAntiAliasing() {
useAntiAliasing = !useAntiAliasing;
repaint();
}
public void pan(double dx, double dy) {
transform.preConcatenate(AffineTransform.getTranslateInstance(dx, dy));
repaint();
}
public void zoomToCenter(double factor) {
zoom(factor, -getWidth() / 2, -getHeight() / 2);
}
public void zoom(double factor, double x, double y) {
if (factor < 1 && zoomFactor < minZoom) {
System.out.println("You can't zoom anymore");
} else if (factor > 1 && zoomFactor > maxZoom) {
System.out.println("You can't zoom anymore");
} else {
zoomFactor *= factor;
System.out.println(zoomFactor);
pan(x, y);
transform.preConcatenate(AffineTransform.getScaleInstance(factor, factor));
pan(-x, -y);
repaint();
}
}
public void toggleDrawingMode() {
drawingModeEnabled = !drawingModeEnabled;
}
public boolean inDrawingMode() {
return drawingModeEnabled;
}
public Point2D toModelCoords(Point2D p) {
try {
return transform.inverseTransform(p, null);
} catch (NoninvertibleTransformException e) {
e.printStackTrace();
}
return null;
}
感谢您的帮助!