I'm trying to make a game in Java (school project) and I have the following setup:
A main class, extended with JFrame, a 'Game' class, extended with JPanel.
Now from within this main class, I make calls to a class 'Player' and a class 'Map'.. The class 'Map' exists of two subclasses 'Blocks' and 'Bombs'.
But I'm wondering.. How do I let the paint methods of all this classes paint to the same JPanel (of the class Game)?
I gave every class the method 'public void paint(Graphics g)' and do the painting.. But only the painting of the class 'Game' shows up when i run the program, not the painting from the subclasses.
How do I implement this?
By example, I reduced my code to this:
Main class:
BomberGame game = new BomberGame();
add(game);
setSize(400, 400);
setTitle("Bomber");
setDefaultCloseOperation(EXIT_ON_CLOSE);
this.show();
}
public static void main(String[] args) {
BomberB1 main = new BomberB1();
}
}
Game class:
package bomberb1;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.ArrayList;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Timer;
public class BomberGame extends JPanel {
public BomberGame() {;
BomberMap map = new BomberMap(this);
}
public void paint(Graphics g) {
g.drawRect(10, 10, 10, 10);
g.setColor(Color.red);
g.fillRect(10, 10, 10, 10);
}
}
Map class:
package bomberb1;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.*;
import javax.swing.SwingUtilities;
public class BomberMap{
BomberGame game;
public BomberMap(BomberGame game) {
this.game = game;
}
public void paint(Graphics g) {
g.drawRect(30, 30, 20, 20);
}
}
In the Entity class (which could be Map player etc) to be drawn have a draw method that accepts a Graphics object thus allowing it to access the Graphics object of the JPanel and draw to it, something like:
class GamePanel extends JPanel {
Entity e=new Entity;
#Override
protected paintComponent(Graphics g) {
super.paintComponent(g);
e.draw(g);//call draw method for entity and pass graphics object
}
}
class Entity {
//will draw whats necessary to Graphics object
public void draw(Graphics g) {
//draw to the graphics object here
}
}
Other suggestions:
Do not extend JFrame class unnecessarily
override JPanel paintComponent() and not paint() (+1 to trashGod comment)
Swing components should be created and manipulated on Event Dispatch Thread via SwingUtilities.invokeLater(..) block.
UPDATE:
As #GuillaumePolet stated a better game design would be implementing JPanels as parent class for most of the game entities see this similar answer for more.
Related
I'm trying to get 2 classes to interact with the same Graphics object but removing a Button component on the 1st class creates an empty space where it used to be after drawRect() is called in the 2nd class.
I have tried a combination of validate(), revalidate() and repaint() in both classes.
1st class:
import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
import testpackage.testing_draw_class;
public class testing_class_draw_main extends Applet implements ActionListener {
Button b;
testing_draw_class test;
Graphics g;
public void init() {
b = new Button("test now!");
add(b);
b.addActionListener(this);
test = new testing_draw_class();
g = getGraphics();
}
public void actionPerformed(ActionEvent e){
remove(b); // removes button
revalidate();
test.paint(g);
}
}
2nd class:
package testpackage;
import java.applet.Applet;
import java.awt.*;
public class testing_draw_class extends Applet {
public void paint(Graphics g){
g.setColor(Color.BLACK);
g.fillRect(0,0,300,300);
}
}
I was expecting a complete black square however there is a gap where the removed button used to be.
Screenshot of problem
I am a beginner programmer trying to create a Pacman game using Java eclipse. I am at the beginning of the process and I'm simply trying to get my main "Princess Pacman" character on the JFrame screen, but, I have this Override error popping up. I have also tried it with out override but it doesn't seem to be working for me that way either.
Here is my code:
import java.awt.*;
import java.awt.image.*;
import java.io.File;
import java.io.IOException;
import java.awt.event.KeyEvent;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class Pacman extends JFrame {
public static final int WIDTH = 500;
public static final int HEIGHT = 500;
public static void main(String args[]){
Pacman gui = new Pacman();
gui.setVisible(true);
}
BufferedImage princess = null;
public Pacman(){
super("Princess Pacman");
//set size of playing space
setSize(WIDTH,HEIGHT);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
try{
princess =ImageIO.read(new File("images/Elsa.jpeg"));
}
catch (IOException e){
System.out.println("image not found");
}
}
#Override
public void draw(Graphics2D g){
g.drawImage(princess.getScaledInstance(100, 100, Image.SCALE_DEFAULT), 0, 0, this);
}
}
draw is not a method defined by JFrame or any of its parent classes, therefore it can't be override
draw is never called by anything that actually paints
You should avoid painting directly to top level containers, there's just to many things been painted onto it.
You can use a JLabel, but there are issues with this. Instead, create a custom class extending from JPanel and override its paintComponent method, making sure you call super.paintComponent before you render the image
Take a closer look at Painting in AWT and Swing, Performing Custom Painting and this for example
You're trying to override a method that does not exist in the JFrame class. Remove the override annotation.
I would like to display an image in an area in my Jframe but the image takes up much space.
I would like to take it fair precise dimensions.
How can I do this in Java
This is my simple code :
I am open to any proposal if I did not use the right method or the right class to instantiate the image.
import java.awt.*;
import javax.swing.*;
public class ExempleDeplace extends JFrame{
private JLabel myLabel;
public ExempleDeplace(){
setLayout(new FlowLayout());
setTitle("Fenetre, modele Duchi");
setSize(500,700);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JLabel j = new JLabel(new ImageIcon("src/images/bateau.png"));
add(j);
setVisible(true);
}
public static void main (String[] args) {
ExempleDeplace c = new ExempleDeplace();
}
}
You can paint the image in a JPanel as the whole panel. Then whenever the panel is resized, the image will be resized along with it. Here's a quick-n-dirty runnable demo:
import java.awt.BorderLayout;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class ImgFrame extends JFrame {
private static BufferedImage IMG;
static{
try {
IMG = ImageIO.read(new File("img/Original_Doge_meme.jpg")); //Replace with your image path
} catch (IOException e) {
e.printStackTrace();
}
}
public ImgFrame(){
add(new ImgPanel(), BorderLayout.CENTER);
setSize(500,700);
setVisible(true);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
class ImgPanel extends JPanel{
#Override
public void paintComponent(Graphics g){
super.paintComponent(g);
g.drawImage(IMG, 0, 0, getWidth(), getHeight(), this);
}
}
public static void main(String[] args){
new ImgFrame();
}
}
It's probably cleaner to just resize the image. I highly recommend the image resizing utility methods provided by filthyrichclients.
I actually highly recommend the book as well, as it was one of the few books that actually demonstrated the power of Swing...
Once you have the code, you will want to call
createCompatibleImage(myImage, myWidth,myHeight);
I am trying to run a very simple Java applet program.
When I used AWT.Label component, I can see the component through appletviewer. The code I am using is:
import java.applet.Applet;
import java.awt.Graphics;
import javax.swing.*;
import java.awt.*;
public class AppletTest extends Applet
{
Label user = new Label("Username", Label.LEFT);
public void paint(Graphics g)
{
g.drawString("Registration Form", 195, 10);
}
public void init()
{
add(user);
}
}
When I use swing.JLabel component, I cannot see any component on the screen except for Registration form printed on top:
import java.applet.Applet;
import java.awt.Graphics;
import javax.swing.*;
import java.awt.*;
public class AppletTest extends JApplet
{
JLabel user = new JLabel("Username", JLabel.LEFT);
public void paint(Graphics g)
{
g.drawString("Registration Form", 195, 10);
}
public void init()
{
add(user);
}
}
What is the issue?
Because paint is a method in JApplet, when you override it, you need to call super.paint(g) so that the parent component can still do it's painting. Your paint method should look something more like this:
#Override
public void paint(Graphics g) {
super.paint(g);
g.drawString("Registration Form", 195, 10);
}
Write a program that fills the window with a larrge ellipse. The ellipse shoud touch the window boundaries, even if the window is resized.
I have the following code:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.Ellipse2D;
import javax.swing.JComponent;
public class EllipseComponent extends JComponent {
public void paintComponent(Graphics g)
{
Graphics2D g2 = (Graphics2D) g;
Ellipse2D.Double ellipse = new Ellipse2D.Double(0,0,150,200);
g2.draw(ellipse);
g2.setColor(Color.red);
g2.fill(ellipse);
}
}
And the main class:
import javax.swing.JFrame;
public class EllipseViewer {
public static void main(String[] args)
{
JFrame frame = new JFrame();
frame.setSize(150, 200);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
EllipseComponent component = new EllipseComponent();
frame.add(component);
frame.setVisible(true);
}
}
in your EllipseComponent you do:
Ellipse2D.Double ellipse = new Ellipse2D.Double(0,0,getWidth(),getHeight());
I'd also recommend the changes given by Hovercraft Full Of Eels. In this simple case it might not be an issue but as the paintComponent method grows in complexity you realy want as little as possible to be computed in the paintComponent method.
Do not resize components within paintComponent. In fact, do not create objects or do any program logic within this method. The method needs to be lean, fast as possible, do drawing, and that's it. You must understand that you do not have complete control over when or even if this method is called, and you certainly don't want to add code to it unnecessarily that may slow it down.
You should create your ellipse in the class's constructor. To resize it according to the JComponent's size and on change of size, use a ComponentListener.:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.Ellipse2D;
import javax.swing.JComponent;
public class EllipseComponent extends JComponent {
Ellipse2D ellipse = null;
public EllipseComponent {
ellipse = new Ellipse2D.Double(0,0,150,200);
addComponentListener(new ComponentAdapter() {
public void componentResized(ComponentEvent e) {
// set the size of your ellipse here
// based on the component's width and height
}
});
}
public void paintComponent(Graphics g)
{
Graphics2D g2 = (Graphics2D) g;
g2.draw(ellipse);
g2.setColor(Color.red);
g2.fill(ellipse);
}
}
Caveat: code not run nor tested