Reputation: 63
I'm attempting at making a slideshow program in Java. Sadly, the image is not appearing in the window. Not sure why...
What I do know is everything runs smoothly without an error occurring (stack trace). The window appears, there is just no image there.
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);
}
Upvotes: 0
Views: 90
Reputation: 347184
So, the main problem is with your while-loop
to select the next image...
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());
}
Basically, this never seems to produce a false
result for one reason or another (you can spend some time debugging it to find out why).
A simpler solution would to generate a List
of the files before you start, then simply use Collections.shuffle
to randimise the List
and remove the first element
Something like...
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();
}
I've added in a ArrayList
called imageFiles
which is a list of all the images in the specified directory and used a Swing Timer
to update the UI. You should be sure to actually apply the image to the JLabel
when you've loaded it, jLabel.setIcon(new ImageIcon(ImageIO.read(imageFile)));
.
Personally I find ImageIO
a better way to read/write images, apart from supporting more image formats, it also throws an IOException
when the file can't be read, is helps in diagnosing any potential issues
If you want a "live" view of the directory instead, then I'd use your haveUsed
List
and simply remove elements from the File
listing
Maybe something like...
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)));
You'll need to change haveUsed
from ArrayList<String>
to ArrayList<File>
though
Upvotes: 2
Reputation:
The problem is the line:
imageIcon = new ImageIcon(list.get(i).toString());
You are not changing the old image, but just updating your reference. You need to replace that with:
imageIcon.setImage(ImageIO.read(new File(list.get(i).toString())));
Upvotes: 2