Drawing using Graphics in Java - 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

Related

Problems with Graphics drawImage

I've been hunting through past StackOverflow posts and trying to figure out why my image won't display.
I know that the ImageIO is fine since I can run getWidth() on my BufferedImage and it returns the correct width.
Here is my Graphic class, followed by my main class.
(I'm sorry for trashy code, I'm new to this.)
Code in Graphic class:
package blackjack;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class Graphic extends JPanel implements ActionListener {
/**
*
*/
private static final long serialVersionUID = 1L;
public JFrame frame = new JFrame("Game Window");
public JPanel layout = new JPanel(new BorderLayout());
public JPanel menu = new JPanel();
public JPanel playing = new JPanel(new BorderLayout());
public JPanel game = new JPanel();
public BufferedImage cardArray[] = new BufferedImage[52];
public void begin() {
//starting menu
}
public void playersTurn() {
menu.add(playing);
Font font = new Font("",Font.PLAIN, 24);
JPanel btnHolder = new JPanel();
JLabel play = new JLabel("Playing:");
JLabel or = new JLabel(" or ");
JLabel question = new JLabel(" ? ");
question.setFont(font);
or.setFont(font);
play.setFont(font);
JButton hit = new JButton("Hit");
JButton stand = new JButton("Stand");
hit.addActionListener(this);
stand.addActionListener(this);
playing.add(play, BorderLayout.WEST);
playing.add(btnHolder, BorderLayout.CENTER);
btnHolder.add(hit);
btnHolder.add(or);
btnHolder.add(stand);
btnHolder.add(question);
}
public void gui() {
//main gui
Dimension imageD = new Dimension(71,96);
Dimension menuD = new Dimension(900,120);
menu.setBorder(BorderFactory.createLineBorder(Color.black));
menu.setPreferredSize(menuD);
JPanel titlePanel = new JPanel();
JLabel title = new JLabel("BlackJack");
title.setFont(new Font("", Font.PLAIN, 14));
titlePanel.add(title);
Graphic gr = new Graphic();
gr.setPreferredSize(imageD);
//adding
frame.add(layout);
layout.add(menu, BorderLayout.SOUTH);
layout.add(titlePanel, BorderLayout.NORTH);
layout.add(gr, BorderLayout.CENTER);
//frame settings
frame.setSize(900, 650);
frame.setResizable(false);
frame.setVisible(true);
}
public void buildPathArray() {
for(int i = 1; i<=52; i++){
BufferedImage im = null;
try {
im = ImageIO.read(new File(Blackjack.getInstallDir() + Blackjack.s + "src" + Blackjack.s + "cardpngs"+ Blackjack.s + (100+i)+".png"));
} catch (IOException e) {
e.printStackTrace();
}
cardArray[i-1]= im;
//System.out.println(Blackjack.getInstallDir() + "\\src\\cardpngs\\" + (100+i)+".png");
}
}
#Override
public void actionPerformed(ActionEvent e) {
if(e.getActionCommand().equals("Hit")) {
} else if(e.getActionCommand().equals("Stand")) {
}
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
//g.setColor(Color.GREEN);
//g.fillOval(20, 20, 20, 20);
g.drawImage(cardArray[0], 0, 0, this);
}
}
Code in my main class:
package blackjack;
import java.nio.file.Path;
import java.nio.file.Paths;
public class Blackjack {
public static String installDir = "";
public static String s = "";
public static void main(String[] args) {
Path currentRelativePath = Paths.get("");
installDir = currentRelativePath.toAbsolutePath().toString();
s = System.getProperty("file.separator");
Graphic gr = new Graphic();
gr.buildPathArray();
gr.gui();
//System.out.println(installDir);
//g.playersTurn();
}
public static String getInstallDir() {
return installDir;
}
}
The output is this:
You're creating one instance of Graphic in your Blackjack class...
public class Blackjack {
public static String installDir = "";
public static String s = "";
public static void main(String[] args) {
//...
Graphic gr = new Graphic();
gr.buildPathArray();
gr.gui();
}
And another in your Graphic class
public void gui() {
//...
Graphic gr = new Graphic();
gr.setPreferredSize(imageD);
//adding
//...
layout.add(gr, BorderLayout.CENTER);
//...
}
But you only initialise the images, using buildPathArray of the instance in you BlackBelt class, which is not what is actually displayed on the screen...
As a general rule of thumb, you shouldn't be creating an instance of JFrame from within another component with the express purpose of display that component. Your Graphic component is also trying to do too much. Instead, I would have a Game class, maybe, which pulled the title, menu and Graphic components together and then put that onto an instance of JFrame
The main reason for this is, is your Graphic class is trying to do too much. It should be solely responsible for display the cards and managing them. The Game class should manage the other UI elements and be responsible for ensuring that the UI meets the current state of the game "model", taking in user input (and listening to events from the other UI elements) and updating the model and responding to events that the model creates, a little more like...
BlackJack...
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class BlackJack {
public static void main(String[] args) {
new BlackJack();
}
public BlackJack() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new Game());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class Game extends JPanel {
private JPanel menu;
private Graphic graphic;
public Game() {
menu = new JPanel() {
#Override
public Dimension getPreferredSize() {
return new Dimension(900, 120);
}
};
menu.setBorder(BorderFactory.createLineBorder(Color.black));
JPanel titlePanel = new JPanel();
JLabel title = new JLabel("BlackJack");
title.setFont(new Font("", Font.PLAIN, 14));
titlePanel.add(title);
Graphic gr = new Graphic();
gr.buildPathArray();
setLayout(new BorderLayout());
add(menu, BorderLayout.SOUTH);
add(titlePanel, BorderLayout.NORTH);
add(gr, BorderLayout.CENTER);
}
}
}
Graphic...
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class Graphic extends JPanel {
private static final long serialVersionUID = 1L;
public BufferedImage cardArray[] = new BufferedImage[52];
public void begin() {
//starting menu
}
public void playersTurn() {
// All of this belongs in Game
}
#Override
public Dimension getPreferredSize() {
return new Dimension(71,96);
}
public void buildPathArray() {
for (int i = 1; i <= 52; i++) {
BufferedImage im = null;
try {
im = ImageIO.read(new File(Blackjack.getInstallDir() + Blackjack.s + "src" + Blackjack.s + "cardpngs" + Blackjack.s + (100 + i) + ".png"));
} catch (IOException e) {
e.printStackTrace();
}
cardArray[i - 1] = im;
//System.out.println(Blackjack.getInstallDir() + "\\src\\cardpngs\\" + (100+i)+".png");
}
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
//g.setColor(Color.GREEN);
//g.fillOval(20, 20, 20, 20);
g.drawImage(cardArray[0], 0, 0, this);
}
}
You might also want to have a look at Model-View-Controller.

ActionListener code triggered twice

I made jbutton and added ActionListner to it but the code in public void actionPerformed(ActionEvent e){} exectues twice.It prints test twice,instead of just once.Here is my code
JButton testbut=new JButton("Test");
ListenForButton2 l=new ListenForButton2();
testbut.addActionListener(l);
private class ListenForButton2 implements ActionListener{
#Override
public void actionPerformed(ActionEvent e) {
if(e.getSource() == testbut){System.out.println("tEST");}
}
}
Here is complete code,in case this is no eneough.Looks like problem was adding two action listeners to my button."if (testbut.getActionListeners().length<1)) testbut.addActionListener(l); "fixed it.But can you find where i added two action listeneres to test button
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Arc2D;
import java.awt.geom.CubicCurve2D;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import java.awt.geom.QuadCurve2D;
import java.awt.geom.Rectangle2D;
import java.awt.geom.RoundRectangle2D;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class Game extends JFrame {
JButton but1 = new JButton("MakeMoney");
JButton button1 = new JButton("Current money");
JButton testbut=new JButton("Make money");
int money = 0;
double currentMoney;
String moneyString = "";
String box1txt="Text for box one";
String[] boxtext={"Newspaper Delivery","Car wash","Pizza Delivery","Donut shop","Shrimp boat","Hockey team","Movie Studio","Bank","Oil Company"};
String[] prices={"60.00","720.00","8,640.00","103,680.00","1,244,160.00","14,929,920.00","179,159,040.00","2.149 billion","25.798 billion"};
public static void main(String[] args) {
new Game();
}
public Game() {
try {
this.setContentPane(new JLabel(new ImageIcon(ImageIO.read(new File("C:/Users/TPC/workspace/ProjectMoney/Resources/backgroundForApp.png")))));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
this.setLayout(new BorderLayout());
button1.setContentAreaFilled(false);
ListenForButton lforButton = new ListenForButton();
but1.addActionListener(lforButton);
JPanel thePanel = new JPanel();
thePanel.add(button1);
thePanel.add(but1);
//thePanel.add(testbut);
this.setSize(1042, 617);
this.setLocationRelativeTo(null);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setTitle("Project Money");
this.add(thePanel, BorderLayout.NORTH);
this.add(new DrawStuff(), BorderLayout.CENTER);
this.setResizable(true);
this.setVisible(true);
Sound sound1 = new Sound();
String sound = "file:C:/Users/TPC/Downloads/sound.wav";
sound1.playMusic(sound);
}
private class ListenForButton implements ActionListener {
public void actionPerformed(ActionEvent e) {
if (e.getSource() == but1) {
money += 10;
moneyString = Integer.toString(money);
button1.setText("$" + moneyString);
}
}
}
private class ListenForButton2 implements ActionListener{
#Override
public void actionPerformed(ActionEvent e) {
if(e.getSource() == testbut){System.out.println("tEST");}
}
}
private class DrawStuff extends JComponent {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D graph2 = (Graphics2D) g;
graph2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
Shape drawRoundRec = new RoundRectangle2D.Double(170,40,250,66,45, 45);
//first num xpos,secound num ypost,third num sirina,fourht num duzina
int x1=170; int y1=40; int x2=250; int y2=66; int def=45;
Shape drawRoundRec2=new RoundRectangle2D.Double(x1,(y1+80),x2,y2,def,def);
Shape drawRoundRec3=new RoundRectangle2D.Double(x1,(y1+80+80),x2,y2,def,def);
Shape drawRoundRec4=new RoundRectangle2D.Double(x1,(y1+80+80+80),x2,y2,def,def);
Shape drawRoundRec5=new RoundRectangle2D.Double(x1,(y1+80+80+80+80),x2,y2,def,def);
Shape drawRoundRect6=new RoundRectangle2D.Double(x1+330,40,250,66,def, def);
Shape drawRoundRect7=new RoundRectangle2D.Double(x1+330,(y1+80),250,66,def, def);
Shape drawRoundRect8=new RoundRectangle2D.Double(x1+330,(y1+80+80),250,66,def, def);
Shape drawRoundRect9=new RoundRectangle2D.Double(x1+330,(y1+80+80+80),250,66,def, def);
Shape drawRoundRect10=new RoundRectangle2D.Double(x1+330,(y1+80+80+80+80),250,66,def, def);
graph2.setPaint(Color.BLACK);
graph2.setColor(Color.LIGHT_GRAY);
graph2.fill(drawRoundRec); graph2.fill(drawRoundRec2);
graph2.fill(drawRoundRec3); graph2.fill(drawRoundRec4); graph2.fill(drawRoundRec5); graph2.fill(drawRoundRect6);
graph2.fill(drawRoundRect7); graph2.fill(drawRoundRect8); graph2.fill(drawRoundRect9); graph2.fill(drawRoundRect10);
graph2.setPaint(Color.BLACK);
graph2.draw(drawRoundRec2); graph2.draw(drawRoundRec3); graph2.draw(drawRoundRec4);
graph2.draw(drawRoundRec5); graph2.draw(drawRoundRect6); graph2.draw(drawRoundRect7); graph2.draw(drawRoundRect8);
graph2.draw(drawRoundRect9); graph2.draw(drawRoundRect10);
Font font=new Font("Serif",Font.PLAIN,30);
g.setFont(font); g.drawString(box1txt,190,80); g.drawString(boxtext[0],190,150); g.drawString(boxtext[1],190,150+80); g.drawString(boxtext[2],190,150+90+70);
g.drawString(boxtext[3],190,150+90+70+80);
g.drawString(boxtext[4],520,80); g.drawString(boxtext[5],520,150); g.drawString(boxtext[6],520,150+80); g.drawString(boxtext[7],520,150+90+70);
g.drawString(boxtext[8],520,150+90+70+80);
g.drawString(prices[0],190,150+30); g.drawString(prices[1],190,150+80+30); g.drawString(prices[2],190,150+90+70+30);
g.drawString(prices[3],190,150+90+70+80+30);
g.drawString(prices[4],520,80+25); g.drawString(prices[5],520,150+30); g.drawString(prices[6],520,150+80+30); g.drawString(prices[7],520,150+90+70+30);
g.drawString(prices[8],520,150+90+70+80+30);
testbut.setLocation(180,70);
Dimension d = new Dimension(100,40);
testbut.setSize(d);
ListenForButton2 l=new ListenForButton2();
if (testbut.getActionListeners().length<1) testbut.addActionListener(l);
this.add(testbut);
}
}
}
Make sure to add your action listener just once.
You get the listeners count via testbut.getActionListeners().length .
Update - multiple calls
Within the paintComponent of the DrawStuff class which extends JComponent you are only adding the listener once. Same as for the first listener.
The difference is, the first is added within a constructor. While the paintComponent method of the JComponent which can be called multiples times.
As to how and when it is called, this answer might help you.

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();
}
});
}
}

Coding a java game - JFrame not working as expected

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.

paintComponent not called when calling JScrollPane

I'm trying to load a background image with a JFileChooser, but when the operation ends, the paintcomponent() method is not called as expected.
[EDIT] for this reason, instead of having a red ball over the background image, I have the red ball only.
I read in several other topics that the instance of my Mappa Object should be added to the frame:
Why is paint()/paintComponent() never called?
paintComponent not being called at the right time
PaintComponent is not being called
But this does not solve my problem: I created a JScrollPane that gets my component in the constructor and linked the JScrollPane and added it in the main frame with
frmEditor.getContentPane().add(scrollabile, BorderLayout.CENTER);
This is the code of the main Gui
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import javax.swing.ImageIcon;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.ScrollPaneConstants;
import javax.swing.UIManager;
public class Gui implements ActionListener {
private JFrame frmEditor;
Mappa content;
private JMenuItem mntmSfondo;
private JScrollPane scrollabile;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Gui window = new Gui();
window.frmEditor.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the application.
*/
public Gui() {
initialize();
}
/**
* Initialize the contents of the frame.
*/
private void initialize() {
frmEditor = new JFrame();
frmEditor.setFont(UIManager.getFont("TextArea.font"));
frmEditor.setBounds(50, 50, 1024, 768);
frmEditor.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frmEditor.getContentPane().setLayout(new BorderLayout(0, 0));
JPanel panelTile = new JPanel();
panelTile.setLayout(new BorderLayout(0, 0));
JPanel panelStrum = new JPanel();
panelStrum.setLayout(new GridLayout(15, 2));
content = new Mappa(null);
content.setMinimumSize(new Dimension(150, 150));
scrollabile = new JScrollPane(content);
scrollabile
.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
scrollabile
.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
frmEditor.getContentPane().add(scrollabile, BorderLayout.CENTER);
inizializzaMenu();
}
/**
* Initialize the menu.
*/
private void inizializzaMenu() {
JMenuBar menuBar = new JMenuBar();
frmEditor.setJMenuBar(menuBar);
JMenu mnFile = new JMenu("File");
mnFile.setFont(UIManager.getFont("TextArea.font"));
JMenu mnAltro = new JMenu("Modify");
mnAltro.setFont(UIManager.getFont("TextArea.font"));
menuBar.add(mnAltro);
mntmSfondo = new JMenuItem("Load Background");
mntmSfondo
.setIcon(new ImageIcon(
Gui.class
.getResource("/com/sun/java/swing/plaf/windows/icons/TreeOpen.gif")));
mntmSfondo.setFont(UIManager.getFont("TextArea.font"));
mntmSfondo.addActionListener(this);
mnAltro.add(mntmSfondo);
}
public void actionPerformed(ActionEvent e) {
Object source = e.getSource();
if (source == mntmSfondo) {
JFileChooser fc = new JFileChooser("tuttiSfondi");
int result = fc.showOpenDialog(null);
if (result == JFileChooser.APPROVE_OPTION) {
File file = fc.getSelectedFile();
try {
content = new Mappa(file);
} catch (Exception ex) {
}
}
if (result == JFileChooser.CANCEL_OPTION) {
}
}
}
}
while this is the code of the class Mappa, that I would like to use to load the background from the JFileChooser.
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import javax.imageio.ImageIO;
import javax.swing.*;
public class Mappa extends JPanel {
Image immagine;
public Mappa(File fileImmagine) {
if (fileImmagine != null ) {
BufferedImage img = null;
try {
img = ImageIO.read(new File(fileImmagine.getPath()));
} catch (IOException e) {
e.printStackTrace();
}
this.immagine = img;
}
repaint();
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.clearRect(0, 0, 4000, 4000);
g.drawImage(immagine, 0, 0, null);
g.setColor(Color.red);
g.fillOval(170, 170, 150, 150);
System.out.println("Called Repaint() on Mappa");
}
}
The problem is not in an incorrect image path, since it loads if I set the path on the Mappa class "manually", by giving the path instead of using new File(fileImmagine.getPath()) in the ImageIO.read, but that paintComponent is called only once, when the constructor of Mappa is called from the Gui class
When you set the background, you only allocate the new Mappa instance, but not actually adding it to any container. Try adding the following:
scrollabile.setViewportView(content);
Or instead, replace an image in the Mappa class. Ie:
public void setImage(File file) throws IOException {
this.immagine = ImageIO.read(file);
repaint();
}
Also, in paintComponent(), you could use panel dimensions to fill the whole area:
g.drawImage(immagine, 0, 0, getWidth(), getHeight(), this);
And don't forget to use a valid ImageObserver as JPanel implements one.
You aren't actually modifying the Mapa instance that you've added to the frame. The line
content = new Mappa(file);
in actionPerformed() doesn't change the panel in the frame, it reassigns the local variable only. You should instead put a method such as updateImage() in Mapa that will update the image that Mapa displays. You will also need to call repaint() after this so that it redraws the new image.

Categories