🔒 Locked
[java] JFrames and Graphics
Advertisement
Original Post
I am having one hell of a time writing a simple strategy game in Java (actually not a full game, just a tech demo). The problem seems to come from drawImage(). I attempt to draw an image (or a hundred of them- it's a tile-based game and I iterate over a matrix of terrain tiles and display them in order) and I get a null pointer exception. g.drawImage(grass, 40, 40, this); gives me a null-pointer exception? The only thing that could possibly be null would be the last argument, "this", or the component that I'm supposed to draw on. I'm using a single JFrame for my game (at least right now) and I was wondering if there were any special or strange conventions with JFrames that I wasn't aware of, and that can make an error like this occur. Any help at all would be greatly apprecieated- this is driving me up the wall.
Could you post the stack trace?
catch(Exception e){e.printStackTrace();};
Quote:
Original post by Pajari
g.drawImage(grass, 40, 40, this); gives me a null-pointer exception? The only thing that could possibly be null would be the last argument, "this", or the component that I'm supposed to draw on.
There is no way "this" is null. What could be null is either "g" or "grass".
shmoove
I've had this problem too. One way around this is to allow your frame-making class to extend the Canvas class and do your drawImage() in the overridden paint(). Other than that, I'd suggest looking in the documentation for methods that can create a Graphics object for a JFrame, since Graphics is abstract and cannot be instantiated.
public class demo extends Canvas implements Runnable{ JFrame jf; Thread thr; public void paint(Graphics g) { //do your image drawing here } public void run() { while(true) { repaint(); } } public static void main(String[] args) { thr = new Thread(this); thr.start(); jf = new JFrame(); thr.start(); jf.add(this); //adds Canvas object to window jf.pack(); jf.setVisible(true); }}
Thanks for the help, everyone. Like I said, it's most apprecieated.
I'm fairly sure that my Graphics object is instantiated and that my images are ok. And I always print the stack trace when I catch an exception- that's how I found out that something in g.drawImage() was null. It did not show up at compile-time as an error (I'm using JCreator 2.5 or something, btw).
And as for shinobi's response, I was thinking about using a canvas before (it would make handling mouse events easier too) and now it looks like that will be the best solution. I've never used threads before, so this should be extremely interesting.
Thanks! I'll post the results later.
[Edited by - Pajari on June 19, 2005 10:41:20 AM]
I'm fairly sure that my Graphics object is instantiated and that my images are ok. And I always print the stack trace when I catch an exception- that's how I found out that something in g.drawImage() was null. It did not show up at compile-time as an error (I'm using JCreator 2.5 or something, btw).
And as for shinobi's response, I was thinking about using a canvas before (it would make handling mouse events easier too) and now it looks like that will be the best solution. I've never used threads before, so this should be extremely interesting.
Thanks! I'll post the results later.
[Edited by - Pajari on June 19, 2005 10:41:20 AM]
I recommend finding out what is really null. To do this, enable assertions at the command line with -ea, then assert pretty much everything.
assert(g != null);
assert(tile != null);
etc, etc...
It is kind of a waste of time to switch to a different solution when you don't even know what the problem is.
assert(g != null);
assert(tile != null);
etc, etc...
It is kind of a waste of time to switch to a different solution when you don't even know what the problem is.
Quote:
Original post by jeeky
I recommend finding out what is really null. To do this, enable assertions at the command line with -ea, then assert pretty much everything.
assert(g != null);
assert(tile != null);
etc, etc...
It is kind of a waste of time to switch to a different solution when you don't even know what the problem is.
I'm pretty sure that everything is instantiated, including the canvas, the frame, the graphics object, all the images, and the integer variables involved. That's why I came here in the first place- I was recieving a null pointer exception at run time and not compile time.
I am assuming based on your reply that you have no idea what assertions are. When you assert something, you are "pretty sure" that it is true. Asserts check whatever you are asserting at run time. Try googleing "java assert" or something like that.
It is quite easy to do as well.
For example,
assert(true == PajariHasNoIdeaWhatAssertsAre);
would be a pretty safe and easy assertion for me to make right now.
You might also want to try to finalize your objects. When you create your objects in your class, you can declare them final, meaning the reference will never change. Doing this will also minimize your uncertainty. In particular, I would load all of your media objects up at once and reference them with final members.
E.g.-
private static final Image tile0 = loadImage0Here...
private static final Image tile1 = loadImage1Here...
private static final Image tile2 = loadImage2Here...
private static final Image tile3 = loadImage3Here...
private static final Image tile4 = loadImage4Here...
Hope that helps. Of course, since you are pretty sure you know what you are doing, you can feel free to ignore us and guess your way to a solution.
It is quite easy to do as well.
For example,
assert(true == PajariHasNoIdeaWhatAssertsAre);
would be a pretty safe and easy assertion for me to make right now.
You might also want to try to finalize your objects. When you create your objects in your class, you can declare them final, meaning the reference will never change. Doing this will also minimize your uncertainty. In particular, I would load all of your media objects up at once and reference them with final members.
E.g.-
private static final Image tile0 = loadImage0Here...
private static final Image tile1 = loadImage1Here...
private static final Image tile2 = loadImage2Here...
private static final Image tile3 = loadImage3Here...
private static final Image tile4 = loadImage4Here...
Hope that helps. Of course, since you are pretty sure you know what you are doing, you can feel free to ignore us and guess your way to a solution.
This is a complete listing that should work once copied and pasted. It doesn't use double buffering, so you'll see a little black flickering.
import java.lang.*;import java.util.*;import java.awt.*;import java.awt.Canvas.*;import java.awt.event.*;import java.awt.Graphics.*;import java.applet.*;import javax.swing.*;class makeframe extends Canvas implements Runnable, KeyListener { int x = 20; int u=50; int y = 20; int v=50; Thread thr; makeframe() { thr = new Thread(this); thr.start(); Graphics g = getGraphics(); Dimension di = new Dimension(400,300); JFrame jf = new JFrame("Test Program"); jf.setDefaultLookAndFeelDecorated(true); jf.setDefaultCloseOperation(jf.EXIT_ON_CLOSE); JPanel jp = new JPanel(); JLabel jl = new JLabel("JLabel!"); jl.setForeground(Color.blue); jp.setBackground(Color.red); jp.setPreferredSize(di); jf.setBounds(0,0,400,300); jp.add(jl); jp.add(this); jf.add(jp); jf.addKeyListener(this); setBounds(0,0,400,300); jf.setSize(di); jf.pack(); jf.setVisible(true); } public void paint(Graphics g) { //System.out.println("Painting"); g.setColor(Color.blue); g.fill3DRect(u, v, x, y, true); } public void run() { while(true) { repaint(); if(x>75) x=20; else x++; if(y>75) y=20; else y++; try { thr.sleep(25); } catch(InterruptedException e) { } } } public void keyPressed(KeyEvent e) { char c = e.getKeyChar(); if(c == 'w' & u<250) u++; if(u==250) u=50; } public void keyReleased(KeyEvent e) { } public void keyTyped(KeyEvent e) { //System.out.println(e.getKeyChar()); }}public class awtdemo { public static void main(String[] args) { makeframe mf = new makeframe(); }}
Monkeyget is right - you can draw on a JFrame that is visible. When using a BufferStrategy, it also works this way.
Alright, nothing is working (and I tried assertions, too). I was right whan I said that my graphics object was instantiated- but I was wrong in assuming that that wasn't a problem, because the graphics object has been null this whole time. Adding a canvas, adding a jpanel into my jframe, using threads and assertions, none of it has changed the fundamental problem that getGraphics(), for whatever reason, is always returning null. I thank all of you profusely for your help, but it really hasn't changed the basic problem that I now have- I guess I just wasn't asking the question correctly.
EDIT: The code.
EDIT: The code.
[source lang = "java"]import java.io.*;import javax.swing.*;import java.awt.*;import java.awt.event.*;import javax.swing.JFileChooser.*;import java.awt.Graphics.*;import java.awt.Color.*;public class Screen extends Canvas implements ActionListener, MouseListener, Runnable{ public TerrainItem[][] land = new TerrainItem[10][10]; public Unit[][] unitMap = new Unit[10][10]; //public Player thePlayer; public Unit current; public File map; public JMenuBar mainMenu; Thread thr; Graphics g; public JMenu file; public JMenu about; public JMenu kingdom; public JMenuItem loadMap; public JMenuItem reviewTroops; public JMenuItem credits; public JMenuItem reviewProduction; public JMenuItem endTurn; private static final Image plains = Toolkit.getDefaultToolkit().getImage("grass.jpg"); private static final Image sand = Toolkit.getDefaultToolkit().getImage("sand.jpg"); private static final Image mountain = Toolkit.getDefaultToolkit().getImage("mountain.bmp"); private static final Image lake = Toolkit.getDefaultToolkit().getImage("lake.bmp"); private static final Image forest = Toolkit.getDefaultToolkit().getImage("forest.jpg"); private static final Image knight = Toolkit.getDefaultToolkit().getImage("knight.bmp"); private static final Image soldier = Toolkit.getDefaultToolkit().getImage("soldier.jpg"); public Screen() { thr = new Thread(this); thr.start(); g = getGraphics(); if(g == null) { System.out.println("dammit..."); } JFrame frame = new JFrame("Swing Test"); frame.setDefaultLookAndFeelDecorated(true); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setBounds(0,0,400,300); Container c = frame.getContentPane(); JPanel area = new JPanel(); area.setPreferredSize(new Dimension(400,400)); area.add(this); mainMenu = new JMenuBar(); file = new JMenu("File"); file.getAccessibleContext().setAccessibleDescription("The main menu for the game."); mainMenu.add(file); kingdom = new JMenu("Kingdom"); kingdom.getAccessibleContext().setAccessibleDescription("another secondary menu."); mainMenu.add(kingdom); about= new JMenu("About"); about.getAccessibleContext().setAccessibleDescription("The secondary menu."); mainMenu.add(about); loadMap = new JMenuItem("Load Map"); loadMap.addActionListener(this); file.add(loadMap); credits = new JMenuItem("Credits"); credits.addActionListener(this); about.add(credits); reviewTroops = new JMenuItem("Review Troops"); reviewTroops.addActionListener(this); kingdom.add(reviewTroops); reviewProduction = new JMenuItem("Review Production"); reviewProduction.addActionListener(this); kingdom.add(reviewProduction); endTurn = new JMenuItem("End Turn"); endTurn.addActionListener(this); file.add(endTurn); frame.setJMenuBar(mainMenu); frame.getContentPane().add(area); frame.pack(); frame.setVisible(true); } public void run() { while(true) { paint(); } } public static void main(String[] args) { Screen window = new Screen(); } public void actionPerformed(ActionEvent event) { if("Load Map".equals(event.getActionCommand())) { int x = ((int)(Math.random() * 4)); for(int k = 0; k < 10; k++) { for(int j = 0; j < 10; j++) { if(x == 0) { land[k][j] = new TerrainItem("lake"); } else if(x == 1) { land[k][j] = new TerrainItem("plains"); } else if(x == 2) { land[k][j] = new TerrainItem("mountain"); } else if(x == 3) { land[k][j] = new TerrainItem("forest"); } else if(x == 4) { land[k][j] = new TerrainItem("sand"); } } } } else if("Review Troops".equals(event.getActionCommand())) { System.out.println("reviewtroops"); } else if("Credits".equals(event.getActionCommand())) { System.out.println("credits"); } else if("End Turn".equals(event.getActionCommand())) { Unit temp; for(int k = 0; k < 10; k++) { for(int j = 0; j <10; j++) { if(unitMap[j][k] != null) { temp = unitMap[j][k]; unitMap[j][k] = null; unitMap[temp.toX][temp.toY] = temp; } } } } } public void mouseClicked(MouseEvent e) { g = getGraphics(); int x = e.getX(); int y = e.getY(); x = (x - (x % 40)) / 40; y = (y - (y % 40)) / 40; if(current == null) { for(int k = 0; k < 10; k++) { for(int j = 0; j <10; j++) { if(unitMap[j][k].getX() == x && unitMap[j][k].getY() == y) { current = unitMap[j][k]; } } } current.toX = current.getX(); current.toY = current.getY(); } else { if((x > (current.getX() + 1)) || (y > (current.getY() + 1)) || (y < (current.getY() - 1)) || (x < (current.getX() - 1))) { g.drawLine(current.getX(), current.getY(), x, y); current.toX = x; current.toY = y; } } } public void mouseReleased(MouseEvent e) {} public void mousePressed(MouseEvent e) {} public void mouseExited(MouseEvent e) {} public void mouseEntered(MouseEvent e) {} public void paint() { g = getGraphics(); if(land != null) { for(int k = 0; k < 10; k++) { for(int j = 0; j <10; j++) { if(g != null) { System.out.println("okay..."); if(land[j][k].getName() == "lake") { g.drawImage(lake, j*40, k*40, this); } if(land[j][k].getName() == "plains") { g.drawImage(plains, j*40, k*40, this); } else if(land[j][k].getName() == "mountain") { g.drawImage(mountain, j*40, k*40, this); } else if(land[j][k].getName() == "forest") { g.drawImage(mountain, j*40, k*40, this); } else if(land[j][k].getName() == "sand") { getGraphics().drawImage(sand, j*40, k*40, this); } if(unitMap[j][k].getName() == "soldier") { g.drawImage(soldier, j*40, k*40, this); } else if(unitMap[j][k].getName() == "knight") { g.drawImage(knight, j*40, k*40, this); } } } } } }}
Hmmm... I'm pretty sure you're calling getGraphics() where you shouldn't. A Graphics instance is generated by the JVM when it is ready to draw your component - the Canvas, for example.
Another way to grab an instance for Graphics is by using a BufferStrategy; since you're probably going to use it for the sake of performance, I recommend you take a look at the FAQ and search for capn midnight's post regarding double buffering.
Son Of Cain
Another way to grab an instance for Graphics is by using a BufferStrategy; since you're probably going to use it for the sake of performance, I recommend you take a look at the FAQ and search for capn midnight's post regarding double buffering.
Son Of Cain
Topic Locked
This topic has been locked by a moderator. New replies are not allowed.
Sign in to reply to this topic.
Advertisement