簡體   English   中英

為什么我的JPanel上的圖像沒有更新?

[英]Why isn't my image updating on my JPanel?

https://pastebin.com/Mfj4pX2c

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


        }
    }

}

因此,我要從面板中刪除組件,並從主面板中刪除子面板。 我可以使圖像消失,但是當我調用創建新圖像的方法時,無法顯示它。

我知道它會創建一個新的圖像文件,因為我可以在文件夾中手動檢查它。

為什么這不起作用?

預期行為:程序具有一個下拉框,其中包含Google提供的三種類型的地圖。 我想選擇一個地圖,然后單擊“獲取地圖”按鈕。

該按鈕調用get map函數,該函數創建一個jlabel,其中包含從Google maps URL創建的圖像圖標。

我只希望程序刪除舊圖像並添加更新的圖像。

觀察到的行為:我可以刪除舊圖像並調用create map函數。 該程序感覺像是掛了一秒鍾,我想是下載新圖像,但實際上並沒有更新圖像。

我知道它正在正確下載圖像,因為我可以在目錄文件夾中手動檢查它。

您將需要使用創建並添加到其中的每個新JLabel在centerPanel上調用revalidate()repaint() 但同樣,不要為此煩惱。 只需交換圖標。

只需更改此:

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

對此:

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

並刪除所有刪除了先前的centerPanel和JLabel的代碼。

例如,

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

同樣根據Titus的注釋,任何長時間運行的代碼都應在不同的線程中運行進程。 對於Swing,規范的解決方案是使用SwingWorker。 有關更多信息,請參見:

課程:Swing中的並發

還要注意,在我的代碼中,JButton及其ActionListener是多余的,因為地圖是通過添加到JComboBox的ItemListener進行更新的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM