我正在尝试用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);
}
答案 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
时将图像实际应用到JLabel
。jLabel.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)));
您需要将haveUsed
从ArrayList<String>
更改为ArrayList<File>
,但
答案 1 :(得分:2)
问题在于:
imageIcon = new ImageIcon(list.get(i).toString());
您没有更改旧图片,只是更新参考。您需要将其替换为:
imageIcon.setImage(ImageIO.read(new File(list.get(i).toString()));;