Search code examples
javaswinggraphics2dswingworker

Swing Graphics object not drawing over image in JLabel


I am creating a Java program that receives and plots GPS coordinates over a TCP socket connection on a 2D image of a map. The constructor creates the JFrame and graphical components and then starts off a SwingWorker thread to handle getting coordinates from the socket and then drawing an oval to represent the fix on the map.

I am able to always receive data over the connection but the program does not reliably draw points over the image.

Any suggestions and thank you!

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();

    }
}

}

Solution

  • You should not be drawing with a Graphics object obtained by calling getGraphics() on a Component. Doing this will give you a Graphics object that doesn't persist and an image that doesn't persist. Instead either draw on a BufferedImage with its Graphics object and display it in the GUI, or iterate through the data collection in the JPanel's paintComponent method and draw with the data obtained.