2015-11-19 77 views
0

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

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

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); 
} 
+1

不要使用'ExecutorService',而是使用一个Swing'Timer',因为它是安全的,当你要更新UI – MadProgrammer

+0

使用@MadProgrammer我已经接受了你的建议,但那不能解决我的问题。但是,谢谢你的提示! –

+0

我不认为这将是“解决方案”,只是对其他潜在问题的补救 – MadProgrammer

回答

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到randimise的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(); 


} 

我已添加到名为imageFilesArrayList,该列表是指定目录中所有图像的列表,并使用Swing Timer来更新UI。当你加载它时,你应该确定将图像实际应用到JLabeljLabel.setIcon(new ImageIcon(ImageIO.read(imageFile)));

我个人觉得ImageIO更好的方式来读/写图片,除了支持多种图像格式,它也抛出时,文件无法读取IOException,是诊断任何潜在的问题

如果帮助你想要的目录中的“活”的观点,而不是,然后我会用你的haveUsedList,只是从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))); 

你需要从ArrayList<String>改变haveUsedArrayList<File>虽然

+0

谢谢你,你来解决方案:P唯一的问题是,图像是巨大的。 Windows照片查看器会缩小它们吗?由于某种原因,这也使图像颠倒了吗?我无法想象它为什么会这样,但我也无法想象为什么我会拍一堆颠倒的照片。 –

+0

某些图像具有“方向”属性,这会影响照片的渲染方向。不幸的是,Java不直接支持这一点。是的,我认为Windows照片查看器确实会对图像应用一些缩放。你可以看看[this](http://stackoverflow.com/questions/11959758/java-maintaining-aspect-ratio-of-jpanel-background-image/11959928#11959928)和[this](http:/ /stackoverflow.com/questions/14115950/quality-of-image-after-resize-very-low-java/14116752#14116752)关于缩放的一些想法 – MadProgrammer

+0

你也可以看一看[this](http:// stackoverflow .com/questions/5905868/how-to-rotate-jpeg-images-based-on-the-orientation-metadata)了解更多关于方向的细节 – MadProgrammer

2

的问题是线:

的ImageIcon =新的ImageIcon(list.get(ⅰ)的ToString());

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

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

+1

虽然这肯定是一个问题,但在我的有限测试中,代码从来没有得到那么远 – MadProgrammer

+0

@MadProgrammer同意,只注意到while循环,保持循环和循环 – Raf