Help with JFrames
I've never used JFrames. I've used applets and I want to switch to JFrames. Do you know of any good tutorials for someone who's never used a JFrame before? I've been googling and I've seen lots of different types of code, nothing helpful for a beginner.
http://java.sun.com/docs/books/tutorial/uiswing/components/frame.html
I'm basically trying to start by converting this code* to using JFrames.
public class GameDisplay extends Applet implements MouseListener, ActionListener
{
GamePlay game;
public static Image[] images;
String [] fonts;
Button reset;
Font font;
int font_size;
public void init()
{
images = loadImages();
game = new GamePlay();
reset = new Button("Reset");
addMouseListener(this);
reset.addActionListener(this);
add(reset);
reset.setLocation(500,100);
font_size = 50;
font = new Font("Sanserif", Font.BOLD, font_size);
}
public void actionPerformed (ActionEvent ae)
{
if(ae.getSource()==reset)
{
System.out.println("new game");
game.reset();
repaint();
}
}
public void mouseClicked (MouseEvent me)
{
if(!game.gameOver)
{
game.moveMade(me.getX(),me.getY());
repaint();
}
}
public void mouseEntered (MouseEvent me) {}
public void mousePressed (MouseEvent me) {}
public void mouseReleased (MouseEvent me) {}
public void mouseExited (MouseEvent me) {}
public void paint(Graphics g)
{
g.drawImage(game.board.display, 0, 0, null);
for(int i=0;i<game.board.pieces.size();i++)//prints all pieces on board in their proper locations
{
Piece p=game.board.pieces.get(i);
g.drawImage(p.display, p.X, p.Y,null);
}
g.setFont(font);
g.setColor(Color.black);
g.drawString(game.message,275,300);
}
private Image[] loadImages()
{
String[] paths =
{
"C:\\Users\\JP\\Projects\\Connect Four\\src\\ConnectFourBoard.gif",
"C:\\Users\\JP\\Projects\\Connect Four\\src\\redpiece.gif",
"C:\\Users\\JP\\Projects\\Connect Four\\src\\blackpiece.gif"
};
Image[] images = new Image[paths.length];
Toolkit t = Toolkit.getDefaultToolkit();
MediaTracker mt = new MediaTracker(this);
for(int j = 0; j >< images.length; j++)
{
images[j] = t.createImage(paths[j]);
mt.addImage(images[j], 0);
}
try
{
mt.waitForAll();
}
catch(InterruptedException e)
{
System.out.println("mt interrupted");
}
return images;
}
}
> I'm basically trying to start by converting this
> code* to using JFrames.
And we wish you lots of luck. Now do you have a specific question?
Use a JPanel for all your Swing UI work. That can just be slapped onto JApplets, JFrames or what-have-you as needed
Well yea I mean, can all the stuff I do in applets, is that still applicable to Jframes? Whats the difference between Jframes and Jpanels and everything
This is what I have so far. I'm getting errors with lines that involve "(this)" because I guess you can't do that in static methods so I'm not really sure what to do. Or if I'm even doing this right. It all worked as an applet though.
public class GameDisplay extends JPanel implements ActionListener
{
public static GamePlay game;
public static Image[] images;
public static JButton reset;
private static void createAndShowGUI()
{
//Create and set up the window.
JFrame frame = new JFrame("GameDisplay");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JLabel emptyLabel = new JLabel("");
reset = new JButton("Reset");
reset.addActionListener(this);
emptyLabel.setPreferredSize(new Dimension(175, 100));
frame.getContentPane().add(emptyLabel, BorderLayout.CENTER);
frame.getContentPane().add(reset);
//Display the window.
frame.pack();
frame.setVisible(true);
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
g.drawImage(game.board.display, 0, 0, null);
for(int i=0;i<game.board.pieces.size();i++)//prints all pieces on board in their proper locations
{
Piece p=game.board.pieces.get(i);
g.drawImage(p.display, p.X, p.Y,null);
}
g.setColor(Color.black);
g.drawString(game.message,275,300);
}
public void actionPerformed (ActionEvent ae)
{
if(ae.getSource()==reset)
{
System.out.println("new game");
game.reset();
repaint();
}
}
private static Image[] loadImages()
{
String[] paths =
{
"C:\\Users\\JP\\Projects\\Connect Four\\src\\ConnectFourBoard.gif",
"C:\\Users\\JP\\Projects\\Connect Four\\src\\redpiece.gif",
"C:\\Users\\JP\\Projects\\Connect Four\\src\\blackpiece.gif"
};
Image[] images = new Image[paths.length];
Toolkit t = Toolkit.getDefaultToolkit();
MediaTracker mt = new MediaTracker(this);
for(int j = 0; j >< images.length; j++)
{
images[j] = t.createImage(paths[j]);
mt.addImage(images[j], 0);
}
try
{
mt.waitForAll();
}
catch(InterruptedException e)
{
System.out.println("mt interrupted");
}
return images;
}
public static void main(String[] args)
{
images = loadImages();
game = new GamePlay();
javax.swing.SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
createAndShowGUI();
}
});
}
get rid of all that static sht. We're talking OOPs here and static just won't do. Make them all instance variables unless you have a darn good reason to make them static.
Specifically:
1) I wouldn't have a static variable for GamePlay within the GamePlay class. In fact I wouldn't have a class variable. Consider creating an instance of GamePlay in a static createAndShow method if you want to test your jpanel inside the jpanel class.
2) The images array and reset JButton should be instance variables.
3) createAndShowGUI should be static. You are correct there, but you have the wrong stuff in createAndShowGUI. You should create your GameDisplay object there and display it. Most of the stuff currently in createAndShowGUI should be in your GameDisplay constructor.
4) The images LoadImages should probably be in your constructor. The game = new GamePlay should be in your createAndShow....
5) In fact, where is your JPanel constructor? You definitely need one.
1) I'm pretty sure I need a GamePlay instance variable or I can't create a game at all. And I can't say game.anything()
5) I don't know what I'd do with a JPanel constructor...I'm pretty confused right now actually
Now I have this. I'm not sure I understand how the GameDisplay constructor will ever get called. I'm not used to ever doing anything in a class that has a main method.
public class GameDisplay extends JPanel implements ActionListener
{
GamePlay game;
Image[] images;
JButton reset;
public GameDisplay()
{
images = loadImages();
game = new GamePlay();
reset = new JButton("Reset");
reset.addActionListener(this);
}
private static void createAndShowGUI()
{
//Create and set up the window.
JFrame frame = new JFrame("GameDisplay");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JLabel emptyLabel = new JLabel("");
frame.getContentPane().add(reset);//THIS LINE GIVES AN ERROR
emptyLabel.setPreferredSize(new Dimension(175, 100));
frame.getContentPane().add(emptyLabel, BorderLayout.CENTER);
//Display the window.
frame.pack();
frame.setVisible(true);
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
g.drawImage(game.board.display, 0, 0, null);
for(int i=0;i<game.board.pieces.size();i++)//prints all pieces on board in their proper locations
{
Piece p=game.board.pieces.get(i);
g.drawImage(p.display, p.X, p.Y,null);
}
g.setColor(Color.black);
g.drawString(game.message,275,300);
}
public void actionPerformed (ActionEvent ae)
{
if(ae.getSource()==reset)
{
System.out.println("new game");
game.reset();
repaint();
}
}
private Image[] loadImages()
{
String[] paths =
{
"C:\\Users\\JP\\Projects\\Connect Four\\src\\ConnectFourBoard.gif",
"C:\\Users\\JP\\Projects\\Connect Four\\src\\redpiece.gif",
"C:\\Users\\JP\\Projects\\Connect Four\\src\\blackpiece.gif"
};
Image[] images = new Image[paths.length];
Toolkit t = Toolkit.getDefaultToolkit();
MediaTracker mt = new MediaTracker(this);
for(int j = 0; j >< images.length; j++)
{
images[j] = t.createImage(paths[j]);
mt.addImage(images[j], 0);
}
try
{
mt.waitForAll();
}
catch(InterruptedException e)
{
System.out.println("mt interrupted");
}
return images;
}
public static void main(String[] args)
{
javax.swing.SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
createAndShowGUI();
}
});
}
I am confused. You are not adding the reset button to the GameDisplay panel? I'm not getting a great feel for the structure of your program. You may need another JPanel class.
Also since game is from another class, you probably shouldn't be accessing the field game.board directly. You probably need accessors and settors. Also should game.message be obtained through accessor?
Addendum: what do your other classes contain? In particular "GamePlay"?
Message was edited by:
petes1234
What about something like this?:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class GameDisplay2 extends JPanel
{
private GamePlay game;
private Image[] images;
private String[] fonts;
private JButton reset;
private Font font;
private int fontSize;
public GameDisplay2() {
super();
images = loadImages();
game = new GamePlay();
reset = new JButton("Reset");
reset.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent arg0)
{
resetButtonAction(arg0);
}
});
add(reset);
//reset.setLocation(500, 100); // can't do unless use null layout manager
fontSize = 50;
font = new Font("Sanserif", Font.BOLD, fontSize);
addMouseListener(new MouseListener()
{
public void mouseClicked(MouseEvent arg0)
{
gameDisplayMouseClickAction(arg0);
}
public void mouseEntered(MouseEvent arg0){}
public void mouseExited(MouseEvent arg0){}
public void mousePressed(MouseEvent arg0){}
public void mouseReleased(MouseEvent arg0){}
});
}
private void gameDisplayMouseClickAction(MouseEvent me)
{
game.moveMade(me.getX(), me.getY());
repaint();
}
private void resetButtonAction(ActionEvent arg0)
{
System.out.println("new game");
game.reset();
repaint();
}
@Override
public void paintComponent(Graphics g)
{
super.paintComponent(g);
// this part leaves a bad taste in my mouth.
// I'm not sure what game.board is, but you seem to be exposing
// fields that shouldn't be exposed. Perhaps you need getters, setters
// or methods here?
g.drawImage(game.board.display, 0, 0, null);
for(int i=0;i < game.board.pieces.size();i++)
{
Piece p=game.board.pieces.get(i);
g.drawImage(p.display, p.X, p.Y,null);
}
g.setFont(font); g.setColor(Color.black);
g.drawString(game.message,275,300);
}
private Image[] loadImages()
{
String[] paths =
{
"C:\\Users\\JP\\Projects\\Connect Four\\src\\ConnectFourBoard.gif",
"C:\\Users\\JP\\Projects\\Connect Four\\src\\redpiece.gif",
"C:\\Users\\JP\\Projects\\Connect Four\\src\\blackpiece.gif"
};
Image[] images = new Image[paths.length];
Toolkit t = Toolkit.getDefaultToolkit();
MediaTracker mt = new MediaTracker(this);
for (int j = 0; j > images.length; j++)
{
images[j] = t.createImage(paths[j]);
mt.addImage(images[j], 0);
}
try
{
mt.waitForAll();
}
catch (InterruptedException e)
{
System.out.println("mt interrupted");
}
return images;
}
private static void createAndShowGUI()
{
JFrame myFrame = new JFrame("Game Display 2");
myFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
myFrame.getContentPane().add(new GameDisplay2());
myFrame.pack();
myFrame.setVisible(true);
}
public static void main(String[] args)
{
javax.swing.SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
createAndShowGUI();
}
});
}
}
Hey thanks, I seem to have got it working. I made a few modifications. I don't really see though, the point of using JFrames instead of an Applet. Things seem to be going slower. What can I now do now that I'm using JFrames instead of an Applet? Can I make an executable or something?
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
public class GameDisplay extends JPanel implements MouseListener, ActionListener
{
private GamePlay game;
public static Image[] images;
private JButton reset;
public GameDisplay()
{
super();//What does super do in this case?
images = loadImages();
game = new GamePlay();
reset = new JButton("Reset");
reset.addActionListener(this);
addMouseListener(this);
add(reset);
}
private static void createAndShowGUI()
{
JFrame frame = new JFrame("GameDisplay");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new GameDisplay());
frame.pack();
frame.setVisible(true);
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
g.drawImage(game.board.display, 0, 0, null);
for(int i=0;i<game.board.pieces.size();i++)//prints all pieces on board in their proper locations
{
Piece p=game.board.pieces.get(i);
g.drawImage(p.display, p.X, p.Y,null);
}
g.setColor(Color.black);
g.drawString(game.message,275,300);
}
public void actionPerformed (ActionEvent ae)
{
if(ae.getSource()==reset)
{
System.out.println("new game");
game.reset();
repaint();
}
}
public void mouseClicked(MouseEvent me)
{
game.moveMade(me.getX(),me.getY());
repaint();
}
public void mouseEntered(MouseEvent me){}
public void mouseExited(MouseEvent me){}
public void mousePressed(MouseEvent me){}
public void mouseReleased(MouseEvent me){}
private Image[] loadImages()
{
String[] paths =
{
"C:\\Documents and Settings\\JP\\My Documents\\Projects\\Connect Four\\src\\ConnectFourBoard.gif",
"C:\\Documents and Settings\\JP\\My Documents\\Projects\\Connect Four\\src\\redpiece.gif",
"C:\\Documents and Settings\\JP\\My Documents\\Projects\\Connect Four\\src\\blackpiece.gif"
};
Image[] images = new Image[paths.length];
Toolkit t = Toolkit.getDefaultToolkit();
MediaTracker mt = new MediaTracker(this);
for(int j = 0; j >< images.length; j++)
{
images[j] = t.createImage(paths[j]);
mt.addImage(images[j], 0);
}
try
{
mt.waitForAll();
}
catch(InterruptedException e)
{
System.out.println("mt interrupted");
}
return images;
}
public static void main(String[] args)
{
javax.swing.SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
createAndShowGUI();
}
});
}
}
Message was edited by:
JFactor2004
Message was edited by:
JFactor2004
You lost your code formatting.
The main thing here is not that you have implemented this as a JFrame, but that you have implemented this as a JPanel. Why is that distinction important? Because as a JPanel you can add this to a JFrame (as done here), and run it as a stand-alone app, OR you can add this to a JApplet and run this as a JApplet, OR, if you desire or need to, heck you could add this to a JDialog and run this as a JDialog. Implementing this as a JPanel gives you flexibility, and THAT is important.
Don't forget JInternalFrame. Love that MDI.
deleted.... the forum is acting funny today.... :(
Message was edited by:
petes1234
So because I said extends JPanel I'm implementing it as a JPanel? And by saying JFrame frame = new JFrame I'm putting the JPanel in a JFrame? How do I now make this a standalone app?
Yes, this:
public class GameDisplay2 extends JPanel
makes it a subclass of JPanel with all rights and privileges. And when you add the class to your JFrame instance, you are putting the jpanel into the jframe. Doing this makes it a stand alone app.
[/code]
private static void createAndShowGUI()
{
JFrame myFrame = new JFrame("Game Display 2"); // creates the JFrame
myFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
myFrame.getContentPane().add(new GameDisplay2()); // adds the JPanel subclass to the JFrame
myFrame.pack();
myFrame.setVisible(true); // this is now a visible stand alone app.
}
[/code]
When I meant standalone, I meant, how do I make it so that it'll be a file that I can double click and it will run? How do I make like an exe file or something?
Also, whenever I run it, it launches as a very small window in corner. I'd like to change the size of it but the setSize command doesn't seem to have any affect
Like an EXE? Create an executable JAR:
http://java.sun.com/docs/books/tutorial/deployment/jar/index.html
Well I'm using eclipse so I figured out how to export to a jar file but when I run it, it doesn't show any images. How do the images become part of the jar file?
It does show the images but if I give this file to somebody else, I'd have to give them the images too right? But the path given in my code is for my computer, so how would it know where to get the images on theres?
The images should be put into the jar file (or a separate jar file, if you want to be able to easily switch between different images sets, say for international apps).
Then, identify the image via a URL, never a file object:
URL url = this.getClass().getResource("foo.png");
BufferedImage bi = ImageIO.read(url);
Here, foo.png is assumed to be in the same folder as the current .class file, in the jar.
You can also provide relative or even "absolute" paths:
URL url = this.getClass().getResource("/images/util/foo.png");
The root of the absolute path is the root of paths in a jar, not the root of your OS's file system.
So I moved all the pictures into the same directory as the class files. I'm not quite sure how to use that code though. I thought of changing the paths to only be ConnectFourBoard.gif etc. since they're all in the bin folder (folder with.class files). I then thought of doing something with an array of URLs but I wasn't sure how to incorporate the rest.
private Image[] loadImages()
{
String[] paths =
{
"C:\\Documents and Settings\\JP\\My Documents\\My Java Projects\\Connect Four\\src\\ConnectFourBoard.gif",
"C:\\Documents and Settings\\JP\\My Documents\\My Java Projects\\Connect Four\\src\\redpiece.gif",
"C:\\Documents and Settings\\JP\\My Documents\\My Java Projects\\Connect Four\\src\\blackpiece.gif"
};
//Code to load images
Image[] images = new Image[paths.length];
Toolkit t = Toolkit.getDefaultToolkit();
MediaTracker mt = new MediaTracker(this);
for(int j = 0; j < images.length; j++)
{
images[j] = t.createImage(paths[j]);
mt.addImage(images[j], 0);
}
try
{
mt.waitForAll();
}
catch(InterruptedException e)
{
System.out.println("mt interrupted");
}
return images;
}
Try again. Those paths are wrong. There is no C drive in your jar!
And use ImageIO -- there's no need for a MediaTracker with it.
> Try again. Those paths are wrong. There is no C drive
> in your jar!
Right. And I can't determine the exact position of a subatomic particle.
As if.
So my code should just be
String[] paths =
{
"ConnectFourBoard.gif",
"redpiece.gif",
"blackpiece.gif"
};
URL[] urls = new URL[paths.length];
BufferedImage bis = new BufferedImage[paths.length];
for (int i =0; i < paths.length; i++)
{urls[i]=this.getClass().getResouce(paths[i]);
bis[i]=ImageIo.read(url[i]);}
Message was edited by:
JFactor2004
not really, I get a compiler error...Do I need a new import?
> not really, I get a compiler error...Do I need a new
> import?
"a compiler error" isn't very useful to us. Which compiler error?
Read [url="http://www.catb.org/~esr/faqs/smart-questions.html"]How To Ask Questions The Smart Way[/url] if you want to know how you can help us help you.
Sorry I meant that, BufferedImage, URL, and ImageIo all can not be resolved to a type
> Sorry I meant that, BufferedImage, URL, and ImageIo
> all can not be resolved to a type
That means you aren't importing them. Did you think you were?
Then take a look at http://java.sun.com/javase/6/docs/api/
Search for those classes, find out which package they are in and add those imports.
P.S.: when did they kill the url-tag? Do they have a quota on the absolute number of features in this forum and whenever they add one they have to remove one?
> Sorry I meant that, BufferedImage, URL, and ImageIo
> all can not be resolved to a type
So import the appropriate packages or use a fully-qualified class name.
~
> P.S.: when did they kill the url-tag?
Back a few weeks when the malicious hackery was running amok.
~
Buy this book: http://www.oreilly.com/catalog/jswing2/index.html
> P.S.: when did they kill the url-tag? Do they have a
> quota on the absolute number of features in this
> forum and whenever they add one they have to remove
> one?
That would imply the number of features in constant, when if fact it is decreasing.
A few weeks ago, someone exploited a hole in the forum software that allowed you to
inject JavaScript in posts to display pictures of himself stretching parts of his body
that were never meant to do that. Sun responded by clenching theirs.
What does fully qualified class mean?
The api says
java.awt.image
Class BufferedImage
But I imported java.awt.*; so shouldn't that import image also?
> But I imported java.awt.*; so shouldn't that import
> image also?
No, "java.awt" and "java.awt.image" are two completely different packages.
~
> But I imported java.awt.*; so shouldn't that import image also?
You mentioned the following couldn't be resolved:
BufferedImage, URL, and ImageIo [actually ImageIO]
Are you adding Image to that list?
edit: nevermind - I though you were talking about class Image, not package java.awt.image...
Message was edited by:
Hippolyte
I thought awt.*; just imported everything with awt in it. Ok, now they are all recognized but now I'm getting a Unhandled exception type IOException from
images=ImageIO.read(urls);
> I thought awt.*; just imported everything with awt in it.
Nope. There is no "package import recursion".
> Ok, now they are all recognized but now I'm
> getting a Unhandled exception type IOException from
> images[n]=ImageIO.read(urls[n]);
So handle it!
~
> now I'm getting a Unhandled exception type IOException
http://java.sun.com/docs/books/tutorial/essential/exceptions/index.html
This seems to work!
Thanks for the pointers, got any more? =)
private Image[] loadImages()
{
String[] paths =
{
"ConnectFourBoard.gif",
"redpiece.gif",
"blackpiece.gif"
};
//Code to load images
BufferedImage[] images = new BufferedImage[paths.length];
URL[] urls = new URL[paths.length];
for(int i =0; i < paths.length; i++)
{
urls[i]=this.getClass().getResource(paths[i]);
try
{
images[i]=ImageIO.read(urls[i]);
}
catch (IOException e)
{
images[i]=null;
}
}
return images;
}
> Thanks for the pointers, got any more? =)
http://www.monochrom.at/zeigerpointer/read.shtml
What? Sorry, I'm just feeling silly right now.
Ok I lied, it doesn't quite work. My jar gets made but when I double click it nothing happens. It used to work but now it doesnt' even open
Run your jar like this to see if it generates a runtime error:
java -jar yourjar.jar
Try to run it from the command line to see if you get any error messages:
java -jar myfile.jar
Illegal argument exception: input == null!
at javax.imageio.ImageIO.read(Unknown source)
and some more stuff
This is the line it points to:
images=ImageIO.read(urls);
Message was edited by:
JFactor2004
Use WinZip or your favorite zip utility to check that the images really are in the jar, in the expected folder.
They weren't in the jar, I thought using the bufferedimage and imageio stuff is what put them there.
> They weren't in the jar, I thought using the
> bufferedimage and imageio stuff is what put them
> there.
So how did you create your jar? If you created it manually,
you forgot to include the images files. Try again:
http://java.sun.com/docs/books/tutorial/deployment/jar/index.html