2015-11-19 119 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