2012-04-07 33 views
3

我目前遇到麻煩的應用程序部分能夠滾動瀏覽並顯示圖像列表,一次一個。我從用戶那裏獲得一個目錄,並在該目錄中的所有文件後面打印,然後加載一個只包含jpegs和png的數組。接下來,我想用第一張圖片更新JLabel,並提供上一個和下一個按鈕,依次滾動並顯示每個圖像。當我嘗試顯示第二圖像,它沒有更新......這就是我這麼遠:更新包含在JLabel中的圖像 - 問題

public class CreateGallery 
{ 
    private JLabel swingImage; 

,我使用更新映像的方法:

protected void updateImage(String name) 
{ 
    BufferedImage image = null; 
    Image scaledImage = null; 
    JLabel tempImage; 

    try 
    { 
     image = ImageIO.read(new File(name)); 
    } catch (IOException e) 
    { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 

    // getScaledImage returns an Image that's been resized proportionally to my thumbnail constraints 
    scaledImage = getScaledImage(image, THUMB_SIZE_X, THUMB_SIZE_Y); 
    tempImage = new JLabel(new ImageIcon(scaledImage)); 
    swingImage = tempImage; 
} 
在放swingImage我createAndShowGUI方法

則...

private void createAndShowGUI() 
{ 
    //Create and set up the window. 
    final JFrame frame = new JFrame(); 

    // Miscellaneous code in here - removed for brevity 

    // Create the Image Thumbnail swingImage and start up with a default image 
    swingImage = new JLabel(); 
    String rootPath = new java.io.File("").getAbsolutePath(); 
    updateImage(rootPath + "/images/default.jpg"); 

    // Miscellaneous code in here - removed for brevity 

    rightPane.add(swingImage, BorderLayout.PAGE_START); 
    frame.add(rightPane, BorderLayout.LINE_END); 
public static void main(String[] args) 
{ 
    SwingUtilities.invokeLater(new Runnable() 
    { 
     public void run() 
     { 
      UIManager.put("swing.boldMetal", Boolean.FALSE); 
      new CreateGalleryXML().createAndShowGUI(); 
     } 
    }); 
} 

如果你已經得到了這一步,第一個圖像是我default.j pg,一旦我得到目錄並確定該目錄中的第一個映像,那麼當我嘗試更新swingImage時,它就會失敗。現在,我試圖swingImage.setVisible()和swingImage.revalidate()來嘗試強制它重新加載。我猜這是我的tempImage =新的JLabel,這是根本原因。但我不知道如何將我的BufferedImage或Image轉換爲JLabel以更新swingImage。

+0

我已經添加了一些關於爲什麼你的'setVisible()/ revalidate()'調用從未在這種情況下工作的信息。希望這會讓這件事變得多一點,至於爲什麼你會得到這個意想不到的行爲:-) – 2012-04-07 06:51:22

+0

我之前嘗試過setVisible(false)的不同組合,而不是在swingImage = tempImage之後將其設置回true。並且在setVisible(true)之前和之後嘗試使用.revalidate()。但我開始相信這是新的JLabel(新的ImageIcon(縮小的圖像),導致這個問題......仍然看着它,並試圖找出它...... – Osh 2012-04-07 06:58:22

回答

8

不是爲每一個Image創建JLabelNew Instance的,只需使用JLabelJLabel#setIcon(...)方法來改變圖像。

一個小樣本程序:

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

public class SlideShow extends JPanel 
{ 
    private int i = 0; 
    private Timer timer; 
    private JLabel images = new JLabel(); 
    private Icon[] icons = {UIManager.getIcon("OptionPane.informationIcon"), 
          UIManager.getIcon("OptionPane.errorIcon"), 
          UIManager.getIcon("OptionPane.warningIcon")}; 
    private ImageIcon pictures1, pictures2, pictures3, pictures4; 
    private ActionListener action = new ActionListener() 
    { 
     public void actionPerformed(ActionEvent ae) 
     {      
      i++; 
      System.out.println(i); 

      if(i == 1) 
      { 
       pictures1 = new ImageIcon("image/caIcon.png"); 
       images.setIcon(icons[i - 1]); 
       System.out.println("picture 1 should be displayed here"); 
      } 
      if(i == 2) 
      { 
       pictures2 = new ImageIcon("image/Keyboard.png"); 
       images.setIcon(icons[i - 1]); 
       System.out.println("picture 2 should be displayed here"); 
      } 
      if(i == 3) 
      { 
       pictures3 = new ImageIcon("image/ukIcon.png"); 
       images.setIcon(icons[i - 1]); 
       System.out.println("picture 3 should be displayed here"); 
      } 
      if(i == 4) 
      { 
       pictures4 = new ImageIcon("image/Mouse.png"); 
       images.setIcon(icons[0]); 
       System.out.println("picture 4 should be displayed here"); 
      } 
      if(i == 5) 
      { 
       timer.stop(); 
       System.exit(0); 
      } 
      revalidate(); 
      repaint(); 
     } 
    }; 

    public SlideShow() 
    { 
     JFrame frame = new JFrame("SLIDE SHOW"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.setLocationByPlatform(true); 

     frame.getContentPane().add(this); 

     add(images); 

     frame.setSize(300, 300); 
     frame.setVisible(true); 
     timer = new Timer(2000, action);  
     timer.start(); 
    } 

    public static void main(String... args) 
    { 
     SwingUtilities.invokeLater(new Runnable() 
     { 
      public void run() 
      { 
       new SlideShow(); 
      } 
     }); 
    } 
} 

既然你的ImageIO做,這裏是與該JLabel using ImageIO

與你的情況下,所發生的事情的信息一個很好的例子:

在您初始化JLabel(swingImage)的createAndShowGUI()方法中,您將其添加到您的JPanel中,憑藉此方法間接向JFrame發送。

但現在你updateImage()方法裏面,要初始化新JLabel,現在它駐留在一些其它的存儲空間,通過寫tempImage = new JLabel(new ImageIcon(scaledImage));並在此之後,你指着你的swingImage(JLabel)指向這個新創建的JLabel,但這個新創建的JLabel從未被添加到JPanel,在任何時候。因此即使您嘗試revalidate()/repaint()/setVisible(...)也不會顯示。因此,要麼你改變代碼爲您updateImage(...)方法是:

protected void updateImage(String name) 
{ 
    BufferedImage image = null; 
    Image scaledImage = null; 
    JLabel tempImage; 

    try 
    { 
     image = ImageIO.read(new File(name)); 
    } 
    catch (IOException e) 
    { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 

    // getScaledImage returns an Image that's been resized 
    // proportionally to my thumbnail constraints 
    scaledImage = getScaledImage(image, THUMB_SIZE_X, THUMB_SIZE_Y); 
    tempImage = new JLabel(new ImageIcon(scaledImage)); 
    rightPane.remove(swingImage); 
    swingImage = tempImage; 
    rightPane.add(swingImage, BorderLayout.PAGE_START); 
    rightPane.revalidate(); 
    rightPane.repaint(); // required sometimes 
} 

或者使用JLabel.setIcon(...)如前所述:-)

更新答案

這裏看到一個New JLabel放置在舊的位置,

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

public class SlideShow extends JPanel 
{ 
    private int i = 0; 
    private Timer timer; 
    private JLabel images = new JLabel(); 
    private Icon[] icons = {UIManager.getIcon("OptionPane.informationIcon"), 
          UIManager.getIcon("OptionPane.errorIcon"), 
          UIManager.getIcon("OptionPane.warningIcon")}; 
    private ActionListener action = new ActionListener() 
    { 
     public void actionPerformed(ActionEvent ae) 
     {      
      i++; 
      System.out.println(i);   

      if(i == 4) 
      { 
       timer.stop(); 
       System.exit(0); 
      } 
      remove(images); 
      JLabel temp = new JLabel(icons[i - 1]); 
      images = temp; 
      add(images); 
      revalidate(); 
      repaint(); 
     } 
    }; 

    private void createAndDisplayGUI() 
    { 
     JFrame frame = new JFrame("SLIDE SHOW"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.setLocationByPlatform(true);  

     this.setLayout(new FlowLayout(FlowLayout.LEFT));  

     add(images); 

     frame.getContentPane().add(this, BorderLayout.CENTER); 

     frame.setSize(300, 300); 
     frame.setVisible(true); 
     timer = new Timer(2000, action);  
     timer.start(); 
    } 

    public static void main(String... args) 
    { 
     SwingUtilities.invokeLater(new Runnable() 
     { 
      public void run() 
      { 
       new SlideShow().createAndDisplayGUI(); 
      } 
     }); 
    } 
} 

而對於你的問題:我試過的兩個選項中,哪一個比另一個更好?

setIcon(...)具有比其他方式的邊緣,在這個意義上,你不必理會重新驗證()/重繪()加入後啄/刪除JLabel。此外,您不必每次都記住您的JLabel的位置,您可以添加它。它仍然處於它的位置,您只需調用一種方法來更改圖像,不附帶任何字符串並完成工作,而不會產生任何麻煩。

而對於問題2:我有點懷疑,至於什麼是Array of Records

+4

好方法;有一個例子[這裏](http: //sites.google.com/site/drjohnbmatthews/googleolympiad)。 – trashgod 2012-04-07 04:19:07

+0

Thankyou,對於那個:-),你確實爲每一種情況都有一個例子,今天毫無疑問,嘿嘿:-) – 2012-04-07 04:33:31

+0

謝謝你!你的swingImage.setIcon(圖標)解決方案工作...我想看看你的改進的updateImage方法,看看它是如何工作的,並且也看@ trashgod的鏈接。再一次,你們倆都幫助我! – Osh 2012-04-07 07:29:48