Wpis z mikrobloga

Ucząc się javy stwierdzilem ze napisze program, który będzie:
- zbierał nazwy i rozszerzenia obrazkow z danego folderu,
- zapisywał je do pliku,
- odczytywał z pliku,
- wyświetlał obrazek w labelu [jako ikona] i zmieniał go na następny lub poprzedni po kliknięciu przycisków.

Używam IntelliJ Idea i NetBeans (do tworzenia gui). Wszystko na Javie 8.
Problem jest taki, że otrzymuje błąd:

Exception in thread "main" java.lang.NullPointerException
at javax.swing.ImageIcon.(ImageIcon.java:217)
at IcoGen.icoRead(IcoGen.java:52)
at Main.main(Main.java:108)

Kombinuję już od dłuższego czasu i nie wiem jak go rozwiązać.
Załączam resztę kodu:

Main.java

import java.io.IOException;

/**
*
* @author dubstep
*/
public class Main extends javax.swing.JFrame {

/**
* Creates new form Main
*/
public Main() {
initComponents();
}

/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
//
private void initComponents() {

Prev = new javax.swing.JButton();
Next = new javax.swing.JButton();
ImgLab = new javax.swing.JLabel();
iG = new IcoGen();

setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

Prev.setText("Prev");
Prev.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
PrevActionPerformed(evt);
}
});

Next.setText("Next");
Next.setToolTipText("");
Next.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
NextActionPerformed(evt);
}
});

ImgLab.setText("Img here");

javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(Prev, javax.swing.GroupLayout.PREFERRED_SIZE, 340, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 20, Short.MAX_VALUE)
.addComponent(Next, javax.swing.GroupLayout.PREFERRED_SIZE, 340, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGroup(layout.createSequentialGroup()
.addComponent(ImgLab, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addContainerGap())
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addComponent(ImgLab, javax.swing.GroupLayout.DEFAULT_SIZE, 344, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(Prev, javax.swing.GroupLayout.PREFERRED_SIZE, 50, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(Next, javax.swing.GroupLayout.PREFERRED_SIZE, 50, javax.swing.GroupLayout.PREFERRED_SIZE)))
);

pack();
}//
public void nextSlide(int currentSlide) {
if (currentSlide < iG.icons.length - 1) {
currentSlide++;
ImgLab.setIcon(iG.icons[currentSlide]);
}
}
public void PrevSlide(int currentSlide) {
if (currentSlide < iG.icons.length - 1) {
currentSlide--;
ImgLab.setIcon(iG.icons[currentSlide]);
}
}

private void PrevActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
PrevSlide(currentSlide);
}

private void NextActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
nextSlide(currentSlide);
}

/**
* @param args the command line arguments
*/
public static void main(String args[]) throws IOException {
/* Set the Nimbus look and feel */
//
/* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
* For details see [http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html](http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html)
*/
IcoGen IcoG = new IcoGen();
IcoG.ListFiles();
IcoG.writeToFile();
IcoG.icoRead();
try {
for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
javax.swing.UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (ClassNotFoundException ex) {
java.util.logging.Logger.getLogger(Main.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (InstantiationException ex) {
java.util.logging.Logger.getLogger(Main.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (IllegalAccessException ex) {
java.util.logging.Logger.getLogger(Main.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (javax.swing.UnsupportedLookAndFeelException ex) {
java.util.logging.Logger.getLogger(Main.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
}
//

/* Create and display the form */
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new Main().setVisible(true);
}
});
}

// Variables declaration - do not modify
private javax.swing.JLabel ImgLab;
private javax.swing.JButton Next;
private javax.swing.JButton Prev;
private int currentSlide = -1;
private IcoGen iG;
// End of variables declaration
}

IcoGen.java

import javax.swing.*;
import java.io.*;

public class IcoGen {
private String[] namesPNG, namesJPG, namesGIF;
public String[] combined;
public int cmbL;
private String dir;
private String line;
private String comm;
public ImageIcon[] icons;
public String[] ListFiles() {
File dir = new File("C:/Users/dubstep/Pictures/");
namesPNG = dir.list(new FilenameFilter() {
public boolean accept(File dir, String name) {
return name.endsWith(".png");
}
});
namesJPG = dir.list(new FilenameFilter() {
public boolean accept(File dir, String name) {
return name.endsWith(".jpg");
}
});
namesGIF = dir.list(new FilenameFilter() {
public boolean accept(File dir, String name) {
return name.endsWith(".gif");
}
});
combined = new String[namesPNG.length + namesJPG.length + namesGIF.length];
int combLenght = namesPNG.length + namesJPG.length;
System.arraycopy(namesPNG, 0, combined, 0, namesPNG.length);
System.arraycopy(namesJPG, 0, combined, namesPNG.length, namesJPG.length);
System.arraycopy(namesGIF, 0, combined, combLenght, namesGIF.length);
cmbL = combined.length;
return combined;
}
public void writeToFile() throws IOException {

BufferedWriter writeNow = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("pics.txt"),"utf-8"));
for (int i = 0; i < cmbL; i++) {
writeNow.write(combined[i]);
writeNow.newLine();
} writeNow.close();
}
public Icon[] icoRead() throws IOException {
BufferedReader read = new BufferedReader(new InputStreamReader(new FileInputStream("pics.txt"),"utf-8"));
dir = "C/Users/dubstep/Pictures/";
for (int j = 0; j < cmbL; j++) {
line = read.readLine();
comm = dir+line;
icons[j] = new ImageIcon(this.getClass().getClassLoader().getResource(comm));
}
read.close();
return icons;
}

}

Ktoś może mi wyjaśnić na czym polega błąd i jak rozwiązać ten i podobne temu typu w przyszłości?
Miło jakby ktoś jeszcze podpowiedział co w kodzie jest nie tak i co można zrobić lepiej.
Uczę się programowania od niedawna.

chyba #programowanie
#naukaprogramowania #java #swing #nullpointerexception
  • 17
@dubstep: Ucz się pisać gui, niż bawić się w klikanie czegoś na edytorze, to jest chyba najlepsza opcja. Druga rzecz porzuć swinga który jest przestarzały. Trzecia, nikt nie używa praktycznie javy do aplikacji desktopowych, tak że jeśli uczysz się javy pod kątem pracy to jest to czas zmarnowany ( ͡~ ͜ʖ ͡°)
@dubstep: naucz się czytać stacktrace'y, oszczędzisz sobie bardzo dużo bólu w dalszej części nauki.

Exception in thread "main" java.lang.NullPointerException <--Nullpo, coś masz niezainicjalizowane
at javax.swing.ImageIcon.(ImageIcon.java:217) <-- w konstruktorze ImageIcon, linia 217
at IcoGen.icoRead(IcoGen.java:52) <-- wywołanym z IcoGen.icoRead, linia 52
at Main.main(Main.java:108) <-- wywołanym z Main, linia 108

Zakładam, że do konstruktora ImageIcon wpada null, czyli linia 52 z IcoGen:

new ImageIcon(this.getClass().getClassLoader().getResource(comm));
https://docs.oracle.com/javase/8/docs/api/java/lang/ClassLoader.html#getResource-java.lang.String-

null if the resource could not be found or
@dubstep: w javafx widoki robisz w scenebuilderze i zapisywane są do fxml, który sobie później programowo ładujesz. Dodatkowo javafx dużo lepiej wspiera wzorzec MVC, a w swingu ciężko znaleźć dobre wzorce i jak piszesz jak w jakichś tutorialach na necie to jest zazwyczaj byle jak bez ładu i składu