2017-10-29 3 views
0

https://pastebin.com/Mfj4pX2cWarum wird mein Bild nicht auf meinem JPanel aktualisiert?

import java.io.FileOutputStream; 
import java.io.IOException; 
import java.io.InputStream; 
import java.io.OutputStream; 
import java.net.URL; 
import java.awt.event.ItemListener; 
import java.awt.event.ItemEvent; 
import java.awt.event.ActionListener; 
import java.awt.event.ActionEvent; 
import javax.swing.ImageIcon; 

import javax.swing.*; 
import java.awt.*; 

public class AWG_Widget extends JPanel { 

    public static final int mapWidth = 300; 
    public static final int mapHeight = 300; 

    BorderLayout layout = new BorderLayout(); 
    JPanel northPanel, centerPanel; 
    JButton bt_GetMap; 
    //Holds the map 
    JLabel map; 
    ImageIcon mapIcon; 
    // Combo Box for the types of maps: roadmap, satellite, terrain 
    String[] mapTypesStringArray = {"roadmap","satellite","terrain"}; 
    String selectedMapType = "satellite"; 
    JComboBox mapTypesComboBox = new JComboBox(mapTypesStringArray); 


    public AWG_Widget(){ 
     // Set layout 
     setLayout(layout); 
     // Sets a border around the pane 
     this.setBorder(BorderFactory.createEtchedBorder()); 

     // inits panels 
     northPanel = new JPanel(new FlowLayout(FlowLayout.CENTER)); 
     centerPanel = new JPanel(new FlowLayout(FlowLayout.CENTER)); 

     // Creates components 
     try { 
      createMap(); 
     } 
     catch (IOException e) { 
      e.printStackTrace(); 
      System.exit(1); 
     } 
     bt_GetMap = new JButton("Get Map!"); 



     // Add components to panels 
     try{ 
      createMap(); 

     } 
     catch(IOException e){ 
      System.out.println("Bad output"); 
     } 

     northPanel.add(mapTypesComboBox); 
     northPanel.add(bt_GetMap); 


     // Add panels to layout 
     add(northPanel, BorderLayout.NORTH); 
     add(centerPanel, BorderLayout.CENTER); 

     // Add Listeners 
     mapTypesComboBox.addItemListener(new ComboBoxItemListener()); 
     bt_GetMap.addActionListener(new ButtonListener()); 
    } 

    public void createMap() throws IOException{ 
     String imageUrl = "https://maps.googleapis.com/maps/api/staticmap?center=10,-11.998672&zoom=6&size=612x612&scale=5&maptype=" + selectedMapType + ""; 
     String destinationFile = "image.jpg"; 
     String str = destinationFile; 
     URL url = new URL(imageUrl); 
     InputStream is = url.openStream(); 
     OutputStream os = new FileOutputStream(destinationFile); 
     byte[] b = new byte[2048]; 
     int length; 

     while ((length = is.read(b)) != -1) { 
      os.write(b, 0, length); 
     } 

     is.close(); 
     os.close(); 

     mapIcon = new ImageIcon((new ImageIcon("image.jpg")).getImage().getScaledInstance(mapWidth, mapHeight, 
      java.awt.Image.SCALE_SMOOTH)); 
     map = new JLabel(mapIcon); 

     centerPanel.add(map); 

    } 

    // Item Listener Class 
    class ComboBoxItemListener implements ItemListener{ 
     @Override 
     public void itemStateChanged(ItemEvent e){ 

      if(e.getStateChange() == ItemEvent.SELECTED){ 

       if(e.getItem().equals("roadmap")){ 
        selectedMapType = "roadmap"; 

       } 
       if(e.getItem().equals("satellite")){ 
        selectedMapType = "satellite"; 

       } 
       if(e.getItem().equals("terrain")){ 
        selectedMapType = "terrain"; 


       } 
      } 
     } 
    } 
    class ButtonListener implements ActionListener { 
     @Override 
     public void actionPerformed(ActionEvent e) { 
      try{ 

       centerPanel.remove(map); 
       remove(centerPanel); 
       repaint(); 
       revalidate(); 

       createMap(); 


       add(centerPanel, BorderLayout.CENTER); 
       revalidate(); 
       repaint(); 
      } 
      catch(IOException ex){ 
       System.out.println("Bad map"); 
      } 
      catch(InterruptedException ex){ 
       System.out.println("Bad map"); 
      } 


     } 
    } 

} 

So Entferne ich die Komponente von der Platte, und die Blendenhalterung aus dem Hauptfeld. Ich kann das Bild verschwinden lassen, aber wenn ich die Methode anrufe, die eine neue erstellt, kann ich nicht sehen, dass sie wieder angezeigt wird.

Ich weiß es erstellen eine neue Bilddatei, weil ich das im Ordner manuell überprüfen kann.

Warum funktioniert das nicht?

Erwartete Verhalten: Das Programm verfügt über eine Dropdown-Box mit den drei Arten von Karten, die Google anbietet. Ich möchte eine Karte auswählen und auf die Schaltfläche "Karte abrufen" klicken.

Die Schaltfläche ruft die Get Map-Funktion auf, die ein Jlabel erstellt, das ein Bildsymbol enthält, das aus der Google Maps-URL erstellt wurde.

Ich möchte nur das Programm das alte Bild entfernen und das aktualisierte Bild hinzufügen.

Beobachtetes Verhalten: Ich kann das alte Bild entfernen und die Funktion create map aufrufen. Das Programm fühlt sich an, als ob es für eine Split Second aufhängt, von der ich denke, dass es das neue Bild herunterlädt, aber es aktualisiert das Bild nicht wirklich.

Ich weiß, dass es das Bild korrekt lädt, weil ich es manuell im Verzeichnisordner überprüfen kann.

+0

Bitte erzählen Sie die Details - Was ist das erwartete Verhalten dieses Programms? Was ist das beobachtete Verhalten? Was passiert * speziell *, das nicht auftreten sollte? Was * speziell * nicht vorkommt, sollte auftreten? Was ist der wichtigste Teil Ihres Codes, und können Sie beschreiben, was er * im Detail * tun soll? –

+0

@HovercraftFullOfEels danke und sorry. Ich habe meinen Beitrag bearbeitet. –

+0

Ich würde Ihr JLabel nicht neu erstellen. Erstellen Sie stattdessen ein einzelnes JLabel-Feld, um das Symbol zu halten, und tauschen Sie die Symbole bei Bedarf einfach aus, indem Sie '.setIcon (...)' auf diesem JLabel aufrufen. Halte es so einfach wie möglich. –

Antwort

2

Sie müssten revalidate() und repaint() auf centerPanel mit jedem neuen JLabel aufrufen, das Sie erstellen und hinzufügen. Aber noch einmal, kümmere dich nicht darum. Einfach Symbole austauschen.

Ganz einfach ändern:

mapLabel = new JLabel(mapIcon); 
centerPanel.add(mapLabel); 

dazu:

mapLabel.setIcon(mapIcon); 
// mapLabel = new JLabel(mapIcon); 
// centerPanel.add(mapLabel); 

und den gesamten Code entfernen, die den Stand der centerPanel und JLabel entfernt.

z.B.

import java.io.IOException; 
import java.net.URL; 
import java.util.concurrent.ExecutionException; 
import java.awt.event.ItemListener; 
import java.awt.image.BufferedImage; 
import java.awt.event.ItemEvent; 
import java.awt.event.ActionListener; 
import java.awt.event.ActionEvent; 

import javax.imageio.ImageIO; 
import javax.swing.*; 
import java.awt.*; 

@SuppressWarnings("serial") 
public class AWG_Widget2 extends JPanel { 
    public static final int MAP_WIDTH = 300; 
    public static final int MAP_HEIGHT = 300; 
    private static final String DEFAULT_GOOGLE_MAP_TEXT = "https://maps.googleapis.com/maps/" 
      + "api/staticmap?center=10,-11.998672&zoom=6&size=612x612&scale=5&maptype="; 
    private Icon defaultIcon = new ImageIcon(
      new BufferedImage(MAP_WIDTH, MAP_HEIGHT, BufferedImage.TYPE_INT_ARGB)); 
    private BorderLayout layout = new BorderLayout(); 
    private JPanel northPanel, centerPanel; 
    private JButton bt_GetMap; 

    // Holds the map 
    private JLabel mapLabel = new JLabel(defaultIcon); 

    // Combo Box for the types of maps: roadmap, satellite, terrain 
    private String[] mapTypesStringArray = { "roadmap", "satellite", "terrain" }; 
    private String selectedMapType = "satellite"; 
    private JComboBox<MapType> mapTypesComboBox = new JComboBox<>(MapType.values()); 
    private String googleMapText = DEFAULT_GOOGLE_MAP_TEXT; 

    public AWG_Widget2() { 
     // Set layout 
     setLayout(layout); 
     // Sets a border around the pane 
     this.setBorder(BorderFactory.createEtchedBorder()); 
     // inits panels 
     northPanel = new JPanel(new FlowLayout(FlowLayout.CENTER)); 
     centerPanel = new JPanel(new FlowLayout(FlowLayout.CENTER)); 
     centerPanel.add(mapLabel); 
     // Creates components 
     try { 
      createMap(MapType.ROADMAP); 
     } catch (IOException e) { 
      e.printStackTrace(); 
      System.exit(1); 
     } 
     bt_GetMap = new JButton("Get Map!"); 

     northPanel.add(mapTypesComboBox); 
     northPanel.add(bt_GetMap); 
     // Add panels to layout 
     add(northPanel, BorderLayout.NORTH); 
     add(centerPanel, BorderLayout.CENTER); 
     // Add Listeners 
     mapTypesComboBox.addItemListener(new ComboBoxItemListener()); 
     bt_GetMap.addActionListener(new ButtonListener()); 
    } 

    private void createMyMap() { 
     mapLabel.setIcon(defaultIcon); 
     try { 
      createMap((MapType) mapTypesComboBox.getSelectedItem()); 
     } catch (IOException e1) { 
      e1.printStackTrace(); 
     } 
    } 

    public void createMap(MapType mapType) throws IOException { 
     new SwingWorker<Icon, Void>() { 
      @Override 
      protected Icon doInBackground() throws Exception { 
       // this code is all done within a background thread 
       String imageUrl = googleMapText + mapType.getText(); 
       URL url = new URL(imageUrl); 
       Image img = ImageIO.read(url); 
       img = img.getScaledInstance(MAP_WIDTH, MAP_HEIGHT, Image.SCALE_SMOOTH); 
       return new ImageIcon(img); 
      } 

      @Override 
      protected void done() { 
       try { 
        // this code is called on the Swing event thread 
        // get returns the Icon created in the doInBackground method 
        mapLabel.setIcon(get()); 
       } catch (InterruptedException e) { 
        e.printStackTrace(); 
       } catch (ExecutionException e) { 
        e.printStackTrace(); 
       } 
      }; 
     }.execute(); // executes our worker 
    } 

    // Item Listener Class 
    class ComboBoxItemListener implements ItemListener { 
     @Override 
     public void itemStateChanged(ItemEvent e) { 
      if (e.getStateChange() == ItemEvent.SELECTED) { 
       createMyMap(); 
      } 
     } 
    } 

    class ButtonListener implements ActionListener { 
     @Override 
     public void actionPerformed(ActionEvent e) { 
      createMyMap(); 
     } 
    } 

    private static void createAndShowGui() { 
     AWG_Widget2 mainPanel = new AWG_Widget2(); 

     JFrame frame = new JFrame("AWG_Widget"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.getContentPane().add(mainPanel); 
     frame.pack(); 
     frame.setLocationRelativeTo(null); 
     frame.setVisible(true); 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(() -> createAndShowGui()); 
    } 
} 

public enum MapType { 
    ROADMAP("roadmap"), SATELLITE("satellite"), TERRAIN("terrain"); 
    private String text; 

    private MapType(String text) { 
     this.text = text; 
    } 

    public String getText() { 
     return text; 
    } 
} 

auch per Titus Kommentar zur Kenntnis, dass jeder lang laufender Code sollte den Prozess in einem anderen Thread ausgeführt werden. Für Swing ist die kanonische Lösung, einen SwingWorker zu verwenden. Weitere Informationen hierzu finden Sie unter:

Lesson: Concurrency in Swing

auch, dass in meinem Code zu beachten, die JButton und seine Action redundant sind, da die Karte aktualisiert wird durch die ItemListener zum JComboBox hinzugefügt.

+1

Sie sollten wahrscheinlich auch die ** I/O ** auf dem ** EDT ** Problem ansprechen. – Titus

+0

@Titus: großer Punkt. Antwort bearbeitet. –

+0

@HovercraftFullOfEels Danke, dieser Code läuft sehr glatt. Wäre es möglich, die Aufzählung meiner AWG_Widget-Klasse ähnlich einer inneren Klasse hinzuzufügen? –

Verwandte Themen