图像未出现在JFrame中

时间:2015-11-19 23:55:18

标签: java image swing

我正在尝试用Java制作幻灯片程序。可悲的是,图像没有出现在窗口中。不知道为什么......

我所知道的是一切顺利运行而没有发生错误(堆栈跟踪)。出现窗口,那里没有图像。

public class Slideshow implements ActionListener, Runnable {
private ArrayList<String> haveUsed = new ArrayList<>();
private JFrame settingsFrame, imageFrame;
private JTextField rootFolder, timeFrame, hiddenRootFolder, hiddenTimeFrame;
private JButton startSlideShow, addRootFolder;
private JLabel jLabel = null;
private ImageIcon imageIcon = null;
public void openSettingsFrame() {
    settingsFrame = new JFrame("Settings - Slideshow v1.0");
    settingsFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    settingsFrame.setLayout(new GridBagLayout());
    GridBagConstraints gbc = new GridBagConstraints();
    settingsFrame.setSize(400, 400);
    gbc.gridx = 0;
    gbc.gridy = 0;
    gbc.insets = new Insets(0, 0, 5, 0);
    hiddenRootFolder = new JTextField("Root Folder:");
    hiddenRootFolder.setEditable(false);
    hiddenRootFolder.setBackground(settingsFrame.getBackground());
    hiddenRootFolder.setBorder(BorderFactory.createLineBorder(settingsFrame.getBackground()));
    settingsFrame.add(hiddenRootFolder, gbc);

    gbc.gridx = 1;
    rootFolder = new JTextField("", 15);
    gbc.insets = new Insets(0, 0, 0, 5);
    rootFolder.setBackground(new Color(255, 255, 255));
    rootFolder.setEditable(false);
    //TODO: add mouse listener
    settingsFrame.add(rootFolder, gbc);

    gbc.gridx = 2;
    addRootFolder = new JButton("Add");
    addRootFolder.addActionListener(this);
    addRootFolder.setSize(80, 20);
    addRootFolder.setPreferredSize(new Dimension(60, 20));
    addRootFolder.setMinimumSize(new Dimension(60, 20));
    settingsFrame.add(addRootFolder, gbc);

    gbc.gridx = 0;
    gbc.gridy = 1;
    hiddenTimeFrame = new JTextField("Speed sec.:");
    gbc.insets = new Insets(0, 0, 5, 0);
    hiddenTimeFrame.setBorder(BorderFactory.createLineBorder(settingsFrame.getBackground()));
    hiddenTimeFrame.setBackground(settingsFrame.getBackground());
    hiddenTimeFrame.setEditable(false);
    settingsFrame.add(hiddenTimeFrame, gbc);

    gbc.gridx = 1;
    timeFrame = new JTextField("", 15);
    settingsFrame.add(timeFrame, gbc);

    gbc.gridx = 0;
    gbc.gridy = 2;
    startSlideShow = new JButton("Start Slideshow");
    startSlideShow.addActionListener(this);
    gbc.fill = GridBagConstraints.HORIZONTAL;
    gbc.gridwidth = 3;
    settingsFrame.add(startSlideShow, gbc);
    settingsFrame.setVisible(true);
}

public static void main(String[] args) {
    new Slideshow().openSettingsFrame();
}


@Override
public void actionPerformed(ActionEvent e) {
    if(e.getSource() == addRootFolder) {
        JFileChooser jfc = new JFileChooser("");
        jfc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
        int returnVal = jfc.showOpenDialog(addRootFolder);
        if(returnVal == JFileChooser.APPROVE_OPTION) {
            File f = jfc.getSelectedFile();
            rootFolder.setText(f.getPath());
        }
    } else if(e.getSource() == startSlideShow) {
        if(!rootFolder.getText().equals("")) {
            if(!timeFrame.getText().equals("")) {
                try {
                    int time = Integer.parseInt(timeFrame.getText());
                    openImageWindow(time);
                } catch (NumberFormatException ex) {
                    ex.printStackTrace();
                }

            }
        } else {
            //TODO: prompt
        }
    }
}

@Override
public void run() {
    File file = new File(rootFolder.getText());
    List list = Arrays.asList(file.list());
    Random random = new Random();
    int i = random.nextInt(list.size());
    while(haveUsed.contains(list.get(i).toString()) || !list.get(i).toString().endsWith(".jpg") ||
            !list.get(i).toString().endsWith(".bmp") || !list.get(i).toString().endsWith(".png")) {
        i = random.nextInt(list.size());
    }
    imageIcon = new ImageIcon(list.get(i).toString());
    imageFrame.repaint();
    imageFrame.revalidate();
    haveUsed.add(list.get(i).toString());
}

public void openImageWindow(int delay) {
    imageFrame = new JFrame("Slideshow v1.0");
    imageFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    imageFrame.setLayout(new BorderLayout());
    imageFrame.setSize(400, 400);
    File file = new File(rootFolder.getText());
    List list = Arrays.asList(file.list());
    Random random = new Random();
    int i = random.nextInt(list.size());
    imageIcon = new ImageIcon(list.get(i).toString());
    haveUsed.add(list.get(i).toString());
    jLabel = new JLabel(imageIcon);
    jLabel.setSize(399, 399);
    imageFrame.add(jLabel);
    ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1);
    scheduledExecutorService.scheduleWithFixedDelay(this, delay, delay, TimeUnit.SECONDS);
    imageFrame.setVisible(true);
}

2 个答案:

答案 0 :(得分:3)

因此,主要问题是您的while-loop选择下一张图片......

while(haveUsed.contains(list.get(i).toString()) || !list.get(i).toString().endsWith(".jpg") ||
        !list.get(i).toString().endsWith(".bmp") || !list.get(i).toString().endsWith(".png")) {
    i = random.nextInt(list.size());
}

基本上,由于某种原因,这似乎永远不会产生false结果(您可以花一些时间调试它以找出原因)。

更简单的解决方案是在开始之前生成List个文件,然后只需使用Collections.shuffle来定义List并删除第一个元素

像...一样的东西。

public void showNextImage() {
    try {
        Collections.shuffle(imageFiles);

        File imageFile = imageFiles.remove(0);

        jLabel.setIcon(new ImageIcon(ImageIO.read(imageFile)));
    } catch (IOException ex) {
        ex.printStackTrace();
    }
}

public void openImageWindow(int delay) {

    imageFiles = new ArrayList<>(Arrays.asList(new File(rootFolder.getText()).listFiles(new FileFilter() {
        @Override
        public boolean accept(File pathname) {
            return pathname.getName().toLowerCase().endsWith(".jpg")
                    || pathname.getName().toLowerCase().endsWith(".png")
                    || pathname.getName().toLowerCase().endsWith(".bmp")
                    || pathname.getName().toLowerCase().endsWith(".gif");
        }
    })));

    imageFrame = new JFrame("Slideshow v1.0");
    imageFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    imageFrame.setLayout(new BorderLayout());
    imageFrame.setSize(400, 400);
    File file = new File(rootFolder.getText());
    List list = Arrays.asList(file.list());
    Random random = new Random();
    int i = random.nextInt(list.size());
    imageIcon = new ImageIcon(list.get(i).toString());
    haveUsed.add(list.get(i).toString());
    jLabel = new JLabel(imageIcon);
    jLabel.setSize(399, 399);
    imageFrame.add(jLabel);
    Timer timer = new Timer(delay, new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            showNextImage();
        }
    });
    imageFrame.setVisible(true);
    timer.setInitialDelay(0);
    timer.start();


}

我添加了名为ArrayList的{​​{1}},它是指定目录中所有图片的列表,并使用Swing imageFiles更新UI。您应确保在加载Timer时将图像实际应用到JLabeljLabel.setIcon(new ImageIcon(ImageIO.read(imageFile)));

我个人认为ImageIO是一种更好的读/写图像方式,除了支持更多图像格式外,当文件无法读取时,它还会抛出IOException,有助于诊断任何图像潜在问题

如果您想要目标的“实时”视图,那么我会使用您的haveUsed List,只需删除File列表中的元素

也许像......

List<File> imageFiles = new ArrayList<>(Arrays.asList(new File(rootFolder.getText()).listFiles(new FileFilter() {
    @Override
    public boolean accept(File pathname) {
        return pathname.getName().toLowerCase().endsWith(".jpg")
                || pathname.getName().toLowerCase().endsWith(".png")
                || pathname.getName().toLowerCase().endsWith(".bmp")
                || pathname.getName().toLowerCase().endsWith(".gif");
    }
})));
imageFiles.removeAll(haveUsed);
Collections.shuffle(imageFiles);

File imageFile = imageFiles.remove(0);
haveUsed(imageFile);

jLabel.setIcon(new ImageIcon(ImageIO.read(imageFile)));

您需要将haveUsedArrayList<String>更改为ArrayList<File>,但

答案 1 :(得分:2)

问题在于:

imageIcon = new ImageIcon(list.get(i).toString());

您没有更改旧图片,只是更新参考。您需要将其替换为:

imageIcon.setImage(ImageIO.read(new File(list.get(i).toString()));;