[英]Swing Graphics object not drawing over image in JLabel
我正在创建一个Java程序,该程序通过TCP套接字连接在地图的2D图像上接收和绘制GPS坐标。 构造函数创建JFrame和图形组件,然后从SwingWorker线程开始以处理从套接字获取坐标,然后绘制一个椭圆形来表示地图上的修复。
我总是能够通过连接接收数据,但是程序无法可靠地在图像上绘制点。
任何建议,谢谢!
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.io.File;
import java.util.List;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingWorker;
import connectivity.TelitSocketServer;
import calculations.PlottingMath;
import objects.ElephantFix;
@SuppressWarnings("serial")
public class Gui
{
protected JFrame mainWindow;
protected JPanel mapArea = new JPanel();
private ReceiveFix rfix;
public Gui()
{
// TODO Auto-generated constructor stub
mainWindow = new JFrame();
// Load map image
Image map = null;
try
{
File mapImage = new File("map_images/AWE_PLOT.JPG");
map = ImageIO.read(mapImage);
} catch (Exception e)
{
System.out.println(e.toString());
}
JLabel label = new JLabel(new ImageIcon(map));
mapArea.add(label);
// Map Image Dimensions
mainWindow.getContentPane().add(mapArea, "Center");
mainWindow.setSize(471, 670);
mainWindow.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainWindow.setTitle("ElePlotter");
mainWindow.setVisible(true);
rfix = new ReceiveFix();
rfix.execute();
}
public static void main(String args[])
{
new Gui();
}
private class ReceiveFix extends SwingWorker<Void, ElephantFix>
{
@Override
protected Void doInBackground()
{
// Start the server
String fix = "";
TelitSocketServer currentConnection = new TelitSocketServer();
try
{
// Wait for client to connect
currentConnection.intializeConnection();
while (true)
{
// Parse and convert received GPS fix into arc radians
fix = currentConnection.readLine();
String[] split = fix.split(" ");
double latWholeDegrees = Double.parseDouble(split[0]
.substring(0, 3));
double longWholeDegrees = Double.parseDouble(split[1]
.substring(0, 3));
double latMinutes = Double.parseDouble(split[0]
.substring(3)) * .166667;
double longMinutes = Double.parseDouble(split[1]
.substring(3)) * .166667;
double lat = latWholeDegrees - latMinutes / 10;
double lon = longWholeDegrees + longMinutes / 10;
publish(new ElephantFix(lat, lon));
}
} catch (Exception e)
{
e.printStackTrace();
}
// Return null if somehow unable to publish node data
return null;
}
@Override
protected void process(List<ElephantFix> fixes)
{
int x, y;
// Get the most recently published node
ElephantFix aFix = fixes.get(fixes.size() - 1);
// Translate lat/long into map X/Y pixel
x = PlottingMath.getCurrentPixelX(aFix.getLatitude(),
aFix.getLongitude());
y = PlottingMath.getCurrentPixelY(aFix.getLatitude(),
aFix.getLongitude());
// Plot on image
Graphics g = mapArea.getGraphics();
g.setColor(Color.RED);
g.fillOval(x, y, 15, 15);
// mapArea.validate();
//
// mapArea.repaint();
//
// Gui.this.repaint();
}
}
}
mapArea.getGraphics();
不是在Swing中完成自定义绘画的方式。
首先查看“ 执行自定义绘画”以获取更多详细信息。
向容器添加组件可确保将子组件始终涂在容器上...
JLabel label = new JLabel(new ImageIcon(map));
mapArea.add(label);
你有倒退。 将label
和mapArea
都添加到同一容器可能更好
您需要克服的下一个问题是,您需要使绘画组件位于标签上方。
为此,您可以...
OverlayLayout
GridBagLayout
用示例更新
有多种方法可以实现此目的,您可以使用多个组件作为层,在这些层上可以添加其他组件或执行自定义绘制。
这听起来并不容易。 大多数布局经理不认为两个组件共享相同的空间。 您还必须管理各层之间的连接,因此,如果地图位于最低层的中心,但是可用空间大于或小于地图,则偏移量开始漂移……混乱……
一个更简单的解决方案是使用单个组件并将所有内容呈现到其上,例如...
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class TestMap {
public static void main(String[] args) {
new TestMap();
}
public TestMap() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
MapPane pane = new MapPane();
pane.dropPinAt(174, 147);
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(pane);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class MapPane extends JPanel {
private BufferedImage img;
private BufferedImage pin;
private List<Point> pins;
public MapPane() {
pins = new ArrayList<>(25);
try {
img = ImageIO.read(getClass().getResource("/Map.jpg"));
pin = ImageIO.read(getClass().getResource("/Pin.png"));
} catch (IOException ex) {
ex.printStackTrace();
}
}
@Override
public Dimension getPreferredSize() {
return img == null ? new Dimension(200, 200) : new Dimension(img.getWidth(), img.getHeight());
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (img != null) {
Graphics2D g2d = (Graphics2D) g.create();
int x = (getWidth() - img.getWidth()) / 2;
int y = (getHeight() - img.getHeight()) / 2;
g2d.drawImage(img, x, y, this);
for (Point p : pins) {
// Offset the pin x/y
// to allow the point to land on the desired location
p.x -= 6;
p.y -= 64;
System.out.println(p);
g2d.drawImage(pin, p.x, p.y, this);
}
g2d.dispose();
}
}
protected void dropPinAt(int x, int y) {
pins.add(new Point(x, y));
}
}
}
您不应使用通过在Component上调用getGraphics()
获得的Graphics对象进行绘图。 这样做将为您提供一个不会持久的Graphics对象和一个不会持久的图像。 取而代之的是使用带有其Graphics对象的BufferedImage并在GUI中显示它,或者遍历JPanel的paintComponent方法中的数据集合并使用获得的数据进行绘制。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.