【发布时间】:2015-05-22 01:58:56
【问题描述】:
首先,一些背景。我正在用 Java 构建我的第一个 GUI 应用程序,但由于我不熟悉 GUI 类,我不确定我是否以正确的方式进行操作。最终目标是根据 Open Street Map 数据构建可调整大小、可缩放、可滚动的地图。
我现在拥有的是 JPanel 的一个子类,我在 JFrame 中调用 LinePanel,并使用 Graphics 对象绘制代表道路的线条。这可以很好地检查我是否正确解析和解释数据,但它似乎不够和幼稚。我已经遇到了一个问题,即 JPanel 在调整大小时被重新绘制多次,导致地图出现错误,以至于我的应用程序需要癫痫警告。
这是我现在的代码:
package map;
import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class MapDisplay {
private JFrame frame;
private LinePanel jpanel;
public MapDisplay(Map map) {
this.frame = new JFrame();
frame.setLayout(new BorderLayout());
frame.addComponentListener(new ComponentAdapter() {
public void componentResized(ComponentEvent e) {
jpanel.repaint();
}
});
jpanel = new LinePanel(map);
frame.add(jpanel, BorderLayout.CENTER);
}
public void display() {
frame.setSize(710, 935);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jpanel.repaint();
}
class LinePanel extends JPanel {
private static final long serialVersionUID = 1965018056953712219L;
private Map map;
private int width;
private int height;
private int latAsY(double lat) {
return height
- (int) (height * (lat - map.getMinLat()) / (map
.getMaxLat() - map.getMinLat()));
}
private int lonAsX(double lon) {
return (int) (width * (lon - map.getMinLong()) / (map.getMaxLong() - map
.getMinLong()));
}
private void recalculateDimensions() {
double mapRatio = (map.getMaxLat() - map.getMinLat())
/ (map.getMaxLong() - map.getMinLong());
double panelRatio = this.getHeight() / (double) this.getWidth();
if (mapRatio > panelRatio) {
width = (int) (this.getHeight() / mapRatio);
height = this.getHeight();
} else {
width = this.getWidth();
height = (int) (mapRatio * this.getWidth());
}
}
public LinePanel(Map map) {
super();
this.map = map;
}
public void repaint() {
if (map != null) {
recalculateDimensions();
Graphics2D g = (Graphics2D) this.getGraphics();
if (g != null) {
g.setStroke(new BasicStroke(2));
g.clearRect(0, 0, jpanel.getWidth(), jpanel.getHeight());
g.setColor(Color.WHITE);
g.fillRect(0, 0, width, height);
g.setColor(Color.BLACK);
for (String wayId : map.getWays()) {
Way way = map.getWay(wayId);
Node prev = null;
for (String nodeId : way.getNodes()) {
Node cur = map.getNode(nodeId);
if (prev != null) {
int y1 = latAsY(prev.getLatitude());
int x1 = lonAsX(prev.getLongitude());
int y2 = latAsY(cur.getLatitude());
int x2 = lonAsX(cur.getLongitude());
g.drawLine(x1, y1, x2, y2);
}
prev = cur;
}
}
}
}
}
}
}
我在调整大小时调用 repaint,因为它不会自动执行此操作,这是我做错了什么的另一个迹象。我还使用 g.fillRect 手动清除 JPanel,因为在重绘地图之前调用 super.repaint() 不会导致任何内容出现...
基本上,我只是想从更高级的 Java 程序员那里得到一些关于我应该如何进行整个工作的指导。如果我走在正确的轨道上,请随意将我推向正确的方向,而不是让我走上新的道路,但我怀疑情况是否如此。
【问题讨论】: