I’m currently working on a Java Swing card game for an assignment, and I ran into a frustrating problem: I kept getting a NullPointerException
whenever I tried to display a card image after clicking a button. After a bit of digging and testing, I finally figured out what was wrong and I’d love to share it with you so you don’t fall into the same trap!
The Problem NullPointerException in Swing
Here’s the simplified version of the original code I wrote in my CardGamePanel.java
class:
Original Code Snippet
Graphics g;
CardGamePanel() {
D.buildDeck();
for (int i = 0; i < cards.length; i++) {
Random r = new Random();
int num1 = r.nextInt(52);
cards[i] = new DisplayableCard("1.png", 30, 30);
}
}
public void go() {
if (count < 9) {
cards[count].display(g); // ERROR HERE
}
count++;
}
And here’s the display method from the DisplayableCard.java
class:
public void display(Graphics g) {
image = new ImageIcon(getClass().getResource(imageFilename)).getImage();
g.drawImage(image, x, y, null); // ERROR HERE
}
The Error
When I clicked the “Flip” button, this error was thrown:
Exception in thread "AWT-EventQueue-1"
java.lang.NullPointerException
at DisplayableCard.display(DisplayableCard.java:16)
at CardGamePanel.go(CardGamePanel.java:31)
At first glance, I thought something was wrong with how I loaded the image. But the real problem was deeper.
What’s Actually Wrong?
The error was coming from Graphics g
, which was null
. I had declared Graphics g
in the class, but I never initialized it. In Java Swing, Graphics
is automatically passed to components when they’re drawn using the paintComponent(Graphics g)
method—not manually!
So by calling cards[count].display(g);
with an uninitialized g
, I was asking Java to draw on nothing!
The Fix Use paintComponent() and Repaint()
To fix the error, I needed to:
- Let Swing handle the graphics.
- Call
repaint()
when I wanted the cards to appear. - Move all drawing logic into the
paintComponent()
method, whereGraphics g
is safely initialized by the system.
Final Working Code
CardGamePanel.java
class CardGamePanel extends JPanel {
private DisplayableCard[] cards = new DisplayableCard[10];
private int count = 0;
public CardGamePanel() {
for (int i = 0; i < cards.length; i++) {
cards[i] = new DisplayableCard("1.png", 30 + i * 40, 30); // Spread cards out
}
}
public void go() {
if (count < cards.length) {
count++;
repaint(); // Triggers paintComponent
}
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
for (int i = 0; i < count; i++) {
cards[i].display(g); // Now g is initialized correctly
}
}
}
DisplayableCard.java
public class DisplayableCard extends Card implements Displayable {
private int x, y;
private Image image;
public DisplayableCard(String filename, int x, int y) {
this.x = x;
this.y = y;
this.image = new ImageIcon(getClass().getResource(filename)).getImage();
}
public void display(Graphics g) {
g.drawImage(image, x, y, null); // Safe to use now
}
}
Simple.java
public class Simple extends JApplet {
private CardGamePanel cgp;
private JButton btnD = new JButton("Flip");
public void init() {
cgp = new CardGamePanel();
JPanel panel2 = new JPanel();
panel2.add(btnD);
btnD.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
cgp.go(); // Safely triggers repaint
}
});
add(cgp, BorderLayout.CENTER);
add(panel2, BorderLayout.SOUTH);
setSize(500, 500);
}
Additional Practice Feature to Add
Now that the error is fixed, here are some fun and educational ideas to improve your card game:
Shuffle the Cards
Collections.shuffle(Arrays.asList(cards));
Add Card Flip Animation
Use javax.swing.Timer
to create a delay and animate the flipping.
Track Score or Turns
private int playerScore = 0;
JLabel scoreLabel = new JLabel("Score: 0");
// Update label when player wins a round
Load Real Card Images Dynamically
String filename = "cards/" + rank + suit + ".png"; // e.g., "2H.png"
Add Multiplayer Support
Alternate turns with a boolean flag:
boolean isPlayer1Turn = true;
Summary
Issue | Solution |
---|---|
NullPointerException caused by using null Graphics | Use paintComponent(Graphics g) |
Manually calling display(g) | Call repaint() to trigger redraw |
Static card positions | Use loops and spacing for layout |
Final Thought
Building this card game has taught me a lot about Swing graphics, event-driven programming, and debugging common Java errors. If you’re also struggling with NullPointerException
, don’t worry it’s one of the most common issues in Java. The key is understanding how Swing handles painting and always letting the framework manage Graphics
.