2014-03-25 69 views
2

我正在創建一個Java程序,該程序通過地圖的2D圖像上的TCP套接字連接接收並繪製GPS座標。構造函數創建JFrame和圖形組件,然後從SwingWorker線程開始處理從套接字獲取座標,然後繪製橢圓以表示地圖上的修復。Swing圖形對象不在JLabel中繪製圖像

我能夠始終通過連接接收數據,但程序不能可靠地在圖像上繪製點。

任何建議,謝謝!

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

    } 
} 

} 

回答

2

你不應該通過對組件調用getGraphics()獲得一個圖形對象繪製。這樣做會給你一個不持久的Graphics對象和一個不會持久的圖像。相反,可以使用其Graphics對象繪製BufferedImage並將其顯示在GUI中,或者遍歷JPanel的paintComponent方法中的數據集合並使用獲得的數據進行繪製。

4

mapArea.getGraphics();是不是如何在Swing中進行自定義繪畫。

首先看Performing Custom Painting瞭解更多詳情。

添加到容器中的組件可確保子組件總是在容器被塗...

JLabel label = new JLabel(new ImageIcon(map)); 
mapArea.add(label); 

您有倒退。將labelmapArea添加到同一容器可能會更好

您需要克服的下一個問題是,您需要讓您的繪畫組件位於標籤的頂部。

爲此你能...

更新與例如

有任何數量可以使用多個組件作爲圖層,您可以在其上添加其他組件或執行自定義繪畫。

這並不像聽起來那麼容易。大多數佈局管理員不會考慮共享相同空間的兩個組件。您還必須管理層之間的連接,所以如果地圖位於最低層內,但可用空間大於或小於地圖,則偏移開始漂移......凌亂......

A簡單的解決辦法是使用單個組件和渲染所有內容到它,例如...

Map

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

} 
+0

謝謝。我不是最熟悉Swing的,所以關於自定義繪畫,我應該如何將我的面板分成另一個類和/或實現繪畫方法?您是否也可以詳細說明關於容器的最後兩點,並將繪畫組件放在標籤上? – akibapower711

+0

@ akibapower711這歸結爲如果你真的需要多個組件來實現你的結果後的結果 – MadProgrammer

+0

我真的很感激這個例子,我相信單一組件渲染將是我需要的。 – akibapower711