Coding a java game - JFrame not working as expected - java

I'd like some help in locating the error I'm making here. I'm relatively new to using Swing and this is the first game I've tried to make.
The problem is as follows: the code compiles fine, but when I run this code, nothing displays in the frame. I've noticed that if I remove the call to grabFrame in the Player class, and uncomment g.drawRect(...), that a rectangle will display in the frame, but when I add the grabFrame call back in, again nothing displays.
GamePanel:
import java.awt.Dimension;
import javax.swing.JFrame;
public class GamePanel extends JFrame {
final static int GWIDTH = 512;
final static int GHEIGHT = 512;
static final Dimension screenSize = new Dimension(GWIDTH, GHEIGHT);
JavaGame game;
public GamePanel () {
this.setTitle("Game");
this.setSize(screenSize);
this.setResizable(false);
this.setVisible(true);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
game = new JavaGame(screenSize);
add(game);
}
public static void main (String[] args) {
GamePanel gp = new GamePanel();
}
}
JavaGame:
import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.JPanel;
class JavaGame extends JPanel {
// Game variables
private GameEngine gameEngine;
public JavaGame(Dimension screenSize) {
this.setPreferredSize(screenSize);
gameEngine = new GameEngine();
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
gameEngine.draw(g);
}
}
GameEngine:
import java.awt.Graphics;
public class GameEngine {
Player p1;
public GameEngine () {
p1 = new Player();
}
public void draw(Graphics g) {
drawCharacters(g);
}
private void drawCharacters(Graphics g) {
p1.draw(g);
}
}
Player:
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import javax.imageio.ImageIO;
public class Player {
private BufferedImage frame;
private URL frameURL;
public Player() {
try {
frameURL = new File("C:/Users/admin/workspace/JavaGame/src/civ_walk_south.png").toURI().toURL();
} catch (MalformedURLException e) {
e.printStackTrace();
}
grabFrame();
}
private void grabFrame() {
try {
frame = ImageIO.read(frameURL);
} catch (IOException e) {
e.printStackTrace();
}
}
public void draw(Graphics g) {
g.drawImage(frame, 50, 50, null);
//g.drawRect(50, 50, 50, 50); // put this here for testing, when uncommented it only works if call to grabFrame() is removed from constructor
}
}

Regarding:
public GamePanel () {
this.setTitle("Game");
this.setSize(screenSize);
this.setResizable(false);
this.setVisible(true); // *****
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
game = new Game(screenSize);
add(game);
}
Call setVisible(true) on your JFrame after adding all components, not before.
So,....
public GamePanel () {
this.setTitle("Game");
// this.setSize(screenSize); // **** don't set sizes like this
this.setResizable(false);
// this.setVisible(true); // *****
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
game = new Game(screenSize);
add(game);
pack(); // **** this should size the GUI to the preferred sizes
setVisible(true); // **** call this here ****
}
Also, have you tested to see if the image obtained is null or not before drawing it?
This smells funny to me as your image path appears to be in a location that will be included inside of the jar file:
frameURL = new File("C:/Users/admin/workspace/JavaGame/src/civ_walk_south.png")
.toURI().toURL();
Why not get your image as a resource and not first as a file?

put add(game) at the topit might also help to setVisible(true) at the very end as well. You also want to call a pack method as well
In the java game class don't declare this.setPreferredSize(screensize) in the java game class instead put it in game panel class also don't just call setPreferredSize() you alos want setMaximumSize() and setMinimumSize() so your game panel class should look like this.
import java.awt.Dimension;
import javax.swing.JFrame;
public class GamePanel extends JFrame {
final static int GWIDTH = 512;
final static int GHEIGHT = 512;
static final Dimension screenSize = new Dimension(GWIDTH, GHEIGHT);
JavaGame game;
public GamePanel () {
game = new JavaGame(screenSize);
game.setPreferredSize(screenSize);
game.setMaximumSize(screenSize);
game.setMinimumSize(screenSize);
add(game);
this.setTitle("Game");
this.setSize(screenSize);
this.setResizable(false);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
}
public static void main (String[] args) {
GamePanel gp = new GamePanel();
}
}
Hope this helps.

Related

Cant paint on JFrame

I am having a problem drawing a JLabel on my JFrame. I already did that in another project and it was working properly, but i messed up somewhere this time and cant draw anymore. Here is my Code:
Board:
import javax.swing.*;
import java.awt.*;
public class Board extends JPanel {
public Board() {
initBoard();
}
private void initBoard() {
setPreferredSize(new Dimension(Frame.GAME_WIDTH, Frame.GAME_HEIGHT));
setMinimumSize(new Dimension(Frame.GAME_WIDTH, Frame.GAME_HEIGHT));
setMaximumSize(new Dimension(Frame.GAME_WIDTH, Frame.GAME_HEIGHT));
setBackground(Color.GRAY);
setDoubleBuffered(true);
}
}
Frame:
import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.border.Border;
import java.awt.*;
import java.io.File;
import java.io.IOException;
public class Frame extends JFrame {
public static final int GAME_WIDTH = 800;
public static final int GAME_HEIGHT = 600;
private final String title = "title here";
private Image backgroundIMG;
public Frame() {
initUI();
}
private void initUI() {
add(new Board());
pack();
setTitle(title);
setSize(GAME_WIDTH, GAME_HEIGHT);
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
setResizable(false);
setLayout(null);
/*
* set background image
*/
/*try {
this.backgroundIMG = ImageIO.read(new File("src/to/image"));
} catch (IOException e) {
e.printStackTrace();
}*/
Border emptyBorder = BorderFactory.createEmptyBorder();
int titleWidth = 270;
int titleHeight = 55;
int titleX = 24;
int titleY = 30;
int titleSize = 47;
String titleFont = "Ravie";
/*
* Customize the startscreen
*/
JLabel title = new JLabel("text");
title.setBounds(0, 0, titleWidth, titleHeight);
title.setFont(new Font(titleFont, Font.BOLD, titleSize));
title.setForeground(new Color(251,102,8));
title.setLocation(titleX, titleY);
add(title);
System.out.println("title should be printed");
}
}
Launcher:
import java.awt.*;
public class Launcher {
public static void main(String[] args) {
EventQueue.invokeLater(() -> {
Frame main = new Frame();
main.setVisible(true);
});
}
}
When i start the program, the Frame is loading up but does not display the JLabel. Its also printing "title should be printed" on the console. I did some research already but wasnt able to find anything that helped me. Maybe its just a trivial error and someone can help me out real quick.
Thanks in advance
Getting past all the, "interesting" stuff for moment, you're basic problem comes down to this...
add(new Board());
//...
add(title);
Java/Swing paint's it's component in LIFO order, so the last component added, is the first component painted.
Probably the most logical fix is to add title to the Board, but you might want to fix a couple of other issues first...
Avoid extending from top level containers like JFrame. Lots of reasons, but mostly, you're not adding new functionality to the class and it's locking you into a single use case which can be better managed through other means/components
Avoid setPreferred/Minimum/MaximumSize. These are more trouble then they are worth. Instead, as required, override getPreferredSize
setDoubleBuffered(true); is pointless, as Swing components are double buffered by default
Avoid null layouts, seriously, this is the number one cause of most of the issues people post about on SO. The layout management API is there for a reason, learn to make use of it.
If we take all that into account, you might end up within something more like...
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.Image;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class Test {
public static void main(String[] args) {
new Test();
}
private final String title = "title here";
public Test() {
EventQueue.invokeLater(() -> {
JFrame main = new JFrame(title);
main.add(new MainPane());
main.pack();
main.setLocationRelativeTo(null);
main.setVisible(true);
});
}
public static final int GAME_WIDTH = 800;
public static final int GAME_HEIGHT = 600;
public static class MainPane extends JPanel {
private Image backgroundIMG;
public MainPane() {
setLayout(new BorderLayout());
setBackground(Color.GRAY);
add(new Board());
String titleFont = "Ravie";
int titleSize = 47;
JLabel title = new JLabel("text");
title.setHorizontalAlignment(JLabel.CENTER);
title.setFont(new Font(titleFont, Font.BOLD, titleSize));
title.setForeground(new Color(251, 102, 8));
add(title, BorderLayout.NORTH);
}
}
public static class Board extends JPanel {
public Board() {
initBoard();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(GAME_WIDTH, GAME_HEIGHT);
}
private void initBoard() {
setBackground(Color.GRAY);
}
}
}

Drawing using Graphics in Java

I have a Graphics question. I'm trying to draw an image in a Frame and I'm having some issue. I want to know what's the best approach to successfully do what I want to do.
I will show my 3 classes. The Main class create the Menu. Once Matchmaking button is press, it create the Board object and call Main.draw to paint all it's component (only Board for now). The picture only sometime appear so it make me realise my code isn't probably setup the right way. THANKS!!!
MAIN CLASS
import java.awt.Graphics;
public class Main
{
public static Board theBoard;
public static void main(String[] args)
{
new Menu("Main Menu").setVisible(true);
}
public static void draw(Graphics painter)
{
theBoard.draw(painter);
}
}
MENU CLASS
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Menu extends JFrame implements ActionListener
{
//Jpanel
JPanel pnlButton = new JPanel();
//Buttons
JButton btnMatchmaking = new JButton("Matchmaking");
JButton btnExit = new JButton("Exit");
JButton btnProfile = new JButton("Profile");
JButton btnOption = new JButton("Options");
public Menu(String s)
{
super("Bu$ted: " + s);
btnExit.addActionListener(this);
btnMatchmaking.addActionListener(this);
//JPanel setting
pnlButton.add(btnMatchmaking);
pnlButton.add(btnProfile);
pnlButton.add(btnOption);
pnlButton.add(btnExit);
pnlButton.setVisible(true);
//The winddow options
super.setLocation(0,0); //A remplacer par des dimension variables
super.setSize(600, 500); //A remplacer par des dimension variables
super.setResizable(false);
super.setVisible(true);
super.add(pnlButton);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
//Handle action events.
//#param evt
#Override
public void actionPerformed(ActionEvent evt)
{
if(evt.getSource() == btnMatchmaking)
{
super.remove(pnlButton);
Main.theBoard = new Board("TestBoard");
super.add(Main.theBoard);
super.setSize(Main.theBoard.boardSize);
Main.draw(super.getGraphics());
}
if(evt.getSource() == btnExit)
{
System.exit(0);
}
}
}
BOARD CLASS
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JPanel;
public class Board extends JPanel
{
BufferedImage boardImage;
int width;
int height;
Dimension boardSize;
public Board (String boardName)
{
boardImage = loadBoard(boardName);
width=boardImage.getWidth();
height=boardImage.getHeight();
boardSize = new Dimension(width,height);
this.setVisible(true);
System.out.println("The board is setup.");
}
private BufferedImage loadBoard (String boardName)
{
BufferedImage img = null;
try
{
img = ImageIO.read(new File("Components/"+boardName+".png"));
}
catch (IOException e)
{
System.out.println("The board image couldn't be loaded.");
}
return img;
}
public void draw(Graphics painter)
{
painter.drawImage(boardImage, 0, 0, null);
System.out.println("The board image was painted.");
}
}
The recommended approach is to override the paintComponent of your Board class and let the paint system handel it...
See Painting in AWT and Swing and Perfoming Custom Painting for more details

Component won't display unless window is resized - Java

I have problem with image visibility after click the button. I have the main class with frame:
package superworld;
import java.awt.*;
import javax.swing.*;
public class SuperWorld {
public static void main(String[] args) {
JFrame frame= new JFrame();
frame.setSize(1050,650);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new SuperPanel());
frame.setVisible(true);
// frame.setResizable(false);
}
}
Then I have class with Panel with all components:
package superworld;
import javax.swing.*;
import java.awt.*;
import java.util.*;
import java.awt.event.*;
import javax.swing.Timer;
public class SuperPanel extends JPanel implements ActionListener{
Timer mainTimer;
public static final int HEIGHT = 550;
public static final int WIDTH = 1050;
int i;
int w=-100;
int h=-50;
ArrayList<SuperMiasto> miasta = new ArrayList<SuperMiasto>();
private JButton heroButton;
private JButton cywilButton;
public SuperPanel() {
mainTimer = new Timer(10,this);
heroButton = new HeroButton(this);
cywilButton = new CywilButton(this);
setLayout(null);
setPreferredSize(new Dimension(WIDTH, HEIGHT));
setBackground(Color.GREEN);
for(i=0;i<10;i++)
{
miasta.add( new SuperMiasto() );
miasta.get(i).x=w;
miasta.get(i).y=h;
miasta.get(i).imagelabel = new JLabel(miasta.get(i).image);
miasta.get(i).imagelabel.setBounds(miasta.get(i).x,miasta.get(i).y,miasta.get(i).image.getIconWidth(),miasta.get(i).image.getIconHeight());
add(miasta.get(i).imagelabel);
w=w+200;
if (w > WIDTH-200)
{
h=h+200;
w=-100;
}
}
}
public void paint(Graphics g){
super.paint(g);
Graphics2D g2d = (Graphics2D) g;
add(heroButton);
add(cywilButton);
}
public void actionPerformed(ActionEvent e) {
repaint();
}
}
And Class with button with add new object with image:
package superworld;
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
class HeroButton extends JButton implements ActionListener {
private JPanel buttonPanel;
HeroButton(JPanel buttonPanel) {
super("Dodaj hero");
this.buttonPanel = buttonPanel;
setBounds(0,500,150,50);
addActionListener(this);
}
#Override
public void actionPerformed(ActionEvent e) {
SuperLudzie batman = new SuperLudzie();
batman.imagelabel = new JLabel(batman.image);
batman.imagelabel.setBounds(50,50,batman.image.getIconWidth(),batman.image.getIconHeight());
buttonPanel.add(batman.imagelabel);
}
}
And class of this SuperLudzie:
package superworld;
import java.awt.*;
import javax.swing.*;
public class SuperLudzie {
private String imie;
private int zycie;
private int inteligencja;
private int wytrzymalosc;
private int sila;
private int umiejetnosci_walki;
private int x,y;
ImageIcon image = new ImageIcon("C:/Users/Zuzanna Sawala/Moje dokumenty/NetBeansProjects/SuperWorld/mysz.jpg");
JLabel imagelabel;
}
Everything work great. I have only problem with this object and image created by button it's not visible just after clicking but after i resize a window. I know that it have something to do with setVisibility(true); but i'm not sure where to use it.
Use SwingUtilities.invokeLater() or EventQueue.invokeLater() to make sure that EDT is initialized properly.
Use overridden paintComponent() method instead of paint()
class SuperPanel extends JPanel {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
...
}
#Override
public Dimension getPreferredSize() {
return new Dimension(..., ...);
}
}
Read more points...
Try to avoid null layout and use proper layout that suits as per our need.
Please have a look at How to Use Various Layout Managers that has sole responsibilities for positioning and sizing of the components.

How to paint on a Jpanel?

i am trying to add 2 different panels in a Frame. one panel adds few buttons in the frame. others frame will add a chess board into the frame. i am confused, how to draw this board on a panel. my Frame will have a board on the top and buttons at the bottom. Moreover, let me know if i am somewhere wrong in the given code can anybody help me? my Code is
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Test {
private JFrame main;
private JPanel board;
private JPanel buttons;
private JButton add;
private JButton delete;
public Test()
{
main=new JFrame();
board=new JPanel();
buttons=new JPanel();
add=new JButton("Add");
delete=new JButton("Delete");
init();
addButtons();
}
public void init()
{
main.setSize(700,700);
main.setVisible(true);
main.setDefaultCloseOperation(main.EXIT_ON_CLOSE);
}
public void addButtons()
{
buttons.setSize(700,40);
buttons.setLayout(new FlowLayout());
buttons.add(add);
buttons.add(delete);
main.add(buttons,BorderLayout.SOUTH);
}
public void addBoxes()
{
// what should be my code here...??
}
public static void main(String[] args) {
// TODO Auto-generated method stub
new Test();
}
}
You need a component to paint on, like a JPanel.
You need to #Override its paintComponent method
You can use a loop to paint using Graphics context
Use a flag to alternate between colors.
Take a look at some Painting Graphics tutorials
In the mean time, give this a whirl
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class Board extends JPanel {
private static final int DIM_WIDTH = 640;
private static final int DIM_HEIGHT = 640;
private static final int SQ_SIZE = 80;
boolean black = true;
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
for (int i = 0; i < DIM_HEIGHT; i += SQ_SIZE) {
if (black) {
black = false;
} else {
black = true;
}
for (int j = 0; j < DIM_WIDTH; j += SQ_SIZE) {
if (black) {
g.setColor(Color.WHITE);
g.fillRect(j, i, SQ_SIZE, SQ_SIZE);
black = false;
} else {
g.setColor(Color.BLACK);
g.fillRect(j, i, SQ_SIZE, SQ_SIZE);
black = true;
}
}
}
}
public static void createAndShowGui() {
JFrame frame = new JFrame();
frame.add(new Board());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationByPlatform(true);
frame.pack();
frame.setVisible(true);
}
public Dimension getPreferredSize() {
return new Dimension(DIM_WIDTH, DIM_HEIGHT);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}

How do I draw an image to a JPanel or JFrame?

How do I draw an Image to a JPanel or JFrame, I have already read oracle's tutorial on this but I can't seem to get it right. I need the image "BeachRoad.png" to be displayed on a specific set of coordinates. Here is what I have so far.
public class Level1 extends JFrame implements ActionListener {
static JLayeredPane EverythingButPlayer;
static Level1 l1;
public Level1() {
EverythingButPlayer = new JLayeredPane();
BufferedImage img = null;
try {
img = ImageIO.read(new File("BeachRoad.png"));
} catch (IOException e) {
}
Graphics g = img.getGraphics();
g.drawImage(img,0, 0, EverythingButPlayer);
this.add(EverythingButPlayer);
}
And in the Main(),
l1 = new Level1();
l1.setTitle("poop");
l1.setSize(1920, 1080);
l1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
l1.setVisible(true);
Thanks in advance!
Try this:
package com.sandbox;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.WindowConstants;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
public class SwingSandbox {
public static void main(String[] args) throws IOException {
JFrame frame = buildFrame();
final BufferedImage image = ImageIO.read(new File("C:\\Projects\\MavenSandbox\\src\\main\\resources\\img.jpg"));
JPanel pane = new JPanel() {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(image, 0, 0, null);
}
};
frame.add(pane);
}
private static JFrame buildFrame() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setSize(200, 200);
frame.setVisible(true);
return frame;
}
}
There are a lot of methods, but I always override the paint(Graphics g) of a JComponent and use g.drawImage(...)
edit: I was making a sample, but Daniel Kaplan did it perfectly, look at his answer :)

Categories