更新JLabel中包含的图像 - 问题

Osh*_*Osh 3 java swing image jlabel

我目前无法开始工作的应用程序的一部分是能够滚动并一次显示一个图像列表.我从用户那里得到一个目录,绕过该目录中的所有文件,然后加载一个只有jpegs和png的数组.接下来,我想用第一个图像更新JLabel,并提供上一个和下一个按钮来滚动并依次显示每个图像.当我尝试显示第二个图像时,它没有得到更新...这是我到目前为止所得到的:

public class CreateGallery
{
    private JLabel swingImage;
Run Code Online (Sandbox Code Playgroud)

我用来更新图像的方法:

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;
}
Run Code Online (Sandbox Code Playgroud)

然后在我的createAndShowGUI方法中放置swingImage ...

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);
Run Code Online (Sandbox Code Playgroud)
public static void main(String[] args) 
{
    SwingUtilities.invokeLater(new Runnable() 
    {
        public void run() 
        {
            UIManager.put("swing.boldMetal", Boolean.FALSE);
            new CreateGalleryXML().createAndShowGUI();
        }
    });
}
Run Code Online (Sandbox Code Playgroud)

如果你已经做到这一点,第一个图像是我的default.jpg,一旦我得到目录并识别该目录中的第一个图像,当我尝试更新swingImage时,它就失败了.现在,我尝试使用swingImage.setVisible()和swingImage.revalidate()来尝试强制重新加载.我猜这是我的tempImage =新的JLabel,这是根本原因.但我不知道如何将我的BufferedImage或Image转换为JLabel以便更新swingImage.

nIc*_*cOw 8

而不是创建的New InstanceJLabel每一个Image,只需使用一个JLabel的setIcon#(...)的方法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 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();
            }
        });
    }
}
Run Code Online (Sandbox Code Playgroud)

由于您使用ImageIO进行此操作,因此这是一个与使用ImageIO的JLabel相关的好示例

与您的案件有关的信息,关于发生的事情:

在你的createAndShowGUI()方法中你初始化你的JLabel(swingImage),并且你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
}
Run Code Online (Sandbox Code Playgroud)

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

更新了答案

在这里看看如何将a 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();
            }
        });
    }
}
Run Code Online (Sandbox Code Playgroud)

对于你的问题:在我尝试的两个选项中,一个比另一个好吗?

setIcon(...)从某种意义上说,在添加/删除之后,你不必为revalidate()/ repaint()添加任何麻烦JLabel.此外,您不需要记住JLabel每次的位置,而是添加它.它保持在它的位置,你只需调用一种方法来改变图像,没有任何附加条件,工作就完成了,没有任何麻烦.

对于问题2:我有点怀疑,至于是什么Array of Records

  • 好方法; 这里有一个例子[http://sites.google.com/site/drjohnbmatthews/googleolympiad]. (4认同)