backgroundImage is null instead of Image [duplicate] - java

This question already has answers here:
How do I compare strings in Java?
(23 answers)
Closed 6 years ago.
I'm relatively new to Java programming and here is some code where it should draw a background Image:
public class Board extends JPanel{
private static final long serialVersionUID = 4759318639631503071L;
public String room = "menu";
public Image backgroundImage;
public Image getBackgroundImage() throws IOException{
if (room == "menu") {
backgroundImage = ImageIO.read(new File("assets/background_title.png"));
}
return backgroundImage;
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(backgroundImage, 0, 0, this);
}
}
I used System.out.println and realized that backgroundImage was null, what have I done wrong here?

You have used == to compare strings
Use if (room.equals("menu"))
instead of
if (room == "menu")

In Java you should compare String objects using equals() method, since == operator checks whether two references point to exactly the same object.
So:
if(room.equals("menu")) { ... }

Related

Java Swing: Is there a way to check for MouseOver for a drawn shape without checking every time the mouse moves?

I have a JPanel that I draw upon. The shapes I draw are some objects stored in a list. I would like to register MouseOvers over these drawn objects. What I am currently doing is adding a MouseMotionListener that checks the list of objects for a hit every time the mouse moves. This is of course pretty inefficient once there are a lot of objects. Is there a better way to check for MouseOvers than just checking all the objects every time the mouse moves?
Here is a minimal example:
class Ui.java:
public class Ui {
private static JFrame frame;
private static DrawPanel drawPanel;
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> { createGui();
});
}
private static void createGui() {
frame = new JFrame("Test");
drawPanel = new DrawPanel();
frame.setContentPane(drawPanel);
frame.pack();
frame.setVisible(true);
frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
}
}
class SomeObject.java:
public class SomeObject {
//class that represents some object that will be drawn. note that this is
//just a minmal example and that in my actual application, there are
//other aspects and functions to this class that have nothing to do with drawing.
//This is just kept small for the sake being a minimal example
private String id;
private Point2D origin;
private int length;
private int height;
public SomeObject(String id, Point2D origin, int length, int height) {
this.id = id;
this.origin = origin;
this.length = length;
this.height = height;
}
public String getId() {
return id;
}
public Point2D getOrigin() {
return origin;
}
public int getLength() {
return length;
}
public int getHeight() {
return height;
}
}
class CustomMouseMotionListener.java:
public class CustomMouseMotionListener implements java.awt.event.MouseMotionListener {
public CustomMouseMotionListener() { }
#Override
public void mouseDragged(MouseEvent e) {
}
#Override
public void mouseMoved(MouseEvent e) {
for (SomeObject object: DrawPanel.objectsToDraw) {
Shape s = new Rectangle((int)object.getOrigin().getX(), (int)object.getOrigin().getY(), object.getLength(), object.getHeight());
if (s.contains(e.getPoint())) {
System.out.println("hit: " + object.getId());
}
}
}
}
class DrawPanel.java:
public class DrawPanel extends JPanel {
public static List<SomeObject> objectsToDraw = new ArrayList<>();
public DrawPanel() {
objectsToDraw.add( new SomeObject("a", new Point2D.Float(20,1), 20,20));
objectsToDraw.add( new SomeObject("b", new Point2D.Float(20,45), 20,20));
addMouseMotionListener(new CustomMouseMotionListener());
setFocusable(true);
setVisible(true);
grabFocus();
}
protected void paintComponent(Graphics g) {
Graphics2D g2D = (Graphics2D) g;
super.paintComponent(g2D);
for (SomeObject object: objectsToDraw) {
g.drawRect((int)object.getOrigin().getX(), (int)object.getOrigin().getY(), object.getLength(), object.getHeight());
}
}
}
Instead of using your SomeObject class, i recommend using Shape or Area. The whole purpose of SomeObject seems to be to be turned into a Shape anyway, right? Not only that, but with an ArrayList of Shapes, you can eliminate creating rectangles for your shapes in every mouseMove.
BTW, years ago I put together a package for treating Areas like 1st class Components. You can see this here: https://sourceforge.net/p/tus/code/HEAD/tree/tjacobs/ui/shape/
(Start with AreaManager and AreaModel). Area has some advantages and disadvantages: Advantages: Easy to manage as a group, fairly easy to test if they are overlapping. Disadvantage: You lose the information about how the Area was constructed (ex. Polygon points, circle radius, etc)
You've already taken this a long way, so kudos to you. This answer is (a) responding to your question about efficiency, but also pointing you in some ways you could choose to go
There is more to SomeObject than just being drawn, so I think I can't just replace it with Shape,
Then you keep a Rectangle instance as part of your SomeObject class, instead of your Point and length/height variables.
Then you modify your methods to return the values from the Rectangle.
This will prevent you from continually creating new Rectangle instances, make the process more memory efficient and reducing garbage collection.
But, you should also be able to extend the Rectangle class and add your extra functionality in the same way that you extend JPanel to add custom painting logic.

Java Update & Refresh BufferedImage on JPanel dynamically

Very new here. Trying to learn Java.
I figured I'd write a very simple "Game Of Life" auto-algorithm to see if I could grasp some of the basics - (The syntax and concepts are pretty straightforward from other languages etc.)
I've managed to muddle through and seem to be "getting the hang of it" but I've reached a pretty steep hill now.
The code described here will compile and is executable, but as you will see, despite the #override to DrawComponent and the repaint() call, the actual image displayed on-screen does not appear to change...
DIRECT QUESTION IS:
How can I ensure the display is updated every "loop"?
FLUFF & SAMPLE SOURCE:
I appreciate the procedural and non-distributed // rigid single encapsulated class here is not the ideal approach for Java, nor is this "game of life" a particularly appropriate use fothe language - BUT Iwanted to focus on getting core elements and understanding first before I 'advance' onto other things. Secondly, I appreciate this is not a very efficient solution either, but again, I wanted to learn by trying something straightforward and readable so I could easily SEE what was happening and ensure it was working properly as expected.
Third, my naming or formatting conventions may be unusual or non-standard, for this I apologise and again appreciate there are preferred ways. This was not necessarily a priority for me in learning how the language works at this time.
I welcome any advice and tips but please consider I am a complete newcomer to using Java so may not be familiar with concepts and terminologies etc.
/*
Project.java
By: PJ Chowdhury
Entire program encapsulated in single class
Created 29-Oct-2018
Updated: 07-Nov-2018
Added graphics library
*/
//Import the basic required graphics classes.
import java.awt.image.BufferedImage;
import java.awt.*;
//Import the basic applet classes.
import javax.swing.*;
//Core class
public class project
{
//Control value - determines when overpopualted or extinct
private static int supercount;
//Control value - how many surrounding cells must be alive for the central cell to survive
private static byte thrive=4;
//Define & declare effective constant size values
private static byte size=64;
private static byte cellsize=4;
//Declare effective singleton arrays of cells
private static boolean[][] cells;
private static boolean[][] prolif;
//Declare Window Frame
public static JFrame frame;
//Declare Graphics
public static JPanel panel;
//main entry-point. Execution must include parameter argument.
public static void main(String[] args)
{
initialise();
do
{
runtime();
defaultcells();
}
while (1>0); //Bad form of course. I wanted an infinite loop. The window can be closed at user request.
}
//Initialises window & graphics frame
public static void initialiseframe()
{
//Create Window
frame = new JFrame("Life Cells");
//Define window parameters
frame.setSize((int)cellsize*size,(int)cellsize*size);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
//Create a window panel to accept graphics
panel = new JPanel()
{
//Overload PaintComponent method to redraw image when the frame panel is redrawn
#Override
public void paintComponent(Graphics g)
{
super.paintComponent(g);
}
};
//attach this panel as a gadget to the frame window
frame.add(panel);
//frame.pack();// Deprecated as this resizes frame window to a minimal size
frame.validate(); // required since panel was added after setVisible was called
frame.repaint(); // required since panel was added after setVisible was called
}
//Initialises & defaults cells
public static void initialisecells()
{
//Define array sizes
cells = new boolean[size][size];
prolif = new boolean[size][size];
// Populate with defaults
defaultcells();
}
//Sets randomised state for each cell
public static void defaultcells()
{
byte x;
byte y;
for (y=0;y<size;y++)
{
for (x=0;x<size;x++)
{
if (Math.random()>=0.5)
{
}
else
{
}
}
}
}
//Wraps initialisation routines
public static void initialise()
{
initialiseframe();
initialisecells();
}
//iterates cells (twice) to determine if they survive or decline and draw to image
public static void process()
{
//Prepare image for cell drawing
Graphics g=panel.getGraphics();
byte x;
byte y;
supercount=0;
//First pass - check if cell will thrive
for (y=0;y<size;y++)
{
for (x=0;x<size;x++)
{
checkcell(x,y);
}
}
//Second pass - apply thrive or wither
for (y=0;y<size;y++)
{
for (x=0;x<size;x++)
{
if (updatecell(x,y))
{
}
if (cells[x][y])
{
}
}
}
}
//sets prolif equivalent depending on status of surrounding cells. This is used in update to set these cells to thrive
public static void checkcell(byte x, byte y)
{
byte count=getsurrounding((int)x,(int)y);
if (count>thrive)
{
prolif[x][y]=true;
}
else
{
if (count<thrive)
{
prolif[x][y]=false;
}
else
{
prolif[x][y]=cells[x][y];
}
}
}
//updates cell with prolif equivalent and returns true if cahnged
public static boolean updatecell(byte x, byte y)
{
if (cells[x][y]!=prolif[x][y])
{
cells[x][y]=prolif[x][y];
return true;
}
return false;
}
//returns number of thriving "cells" surrounding cell at given coords
public static byte getsurrounding(int x, int y)
{
int u=(x-1);
int v=(y-1);
int ux;
int vy;
byte count=0;
for (v=(y-1);v<(y+2);v++)
{
//Use wraparound for edge cells
vy=(v+size) % size;
for (u=(x-1);u<(x+2);u++)
{
//Use wraparound for edge cells
ux=(u+size) % size;
//Only for surrounding cells, not this cell
if ((ux!=x) & (vy!=y))
{
}
}
}
return count;
}
//Draw cell at x,y : not the most efficient nor elegant method...
public static void drawcell(Graphics g, int x, int y, boolean live)
{
if (live)
{
// Draw this cell alive
//g.setColor(Color.GREEN);
}
else
{
// Draw this cell dead
g.setColor(Color.BLACK);
}
g.fillRect(x*cellsize, y*cellsize,cellsize,cellsize);
panel.repaint(x*cellsize, y*cellsize,cellsize,cellsize);
}
//Returns true if population is healthy. False if extinct or overcrowded
public static boolean populationanalysis()
{
return ((supercount<thrive)||(supercount>(int)(size*size)<<1));
}
//Main Loop method
public static void runtime()
{
int sanity=5000;
int loopcount=0;
do
{
process();
loopcount++;
if (populationanalysis())
{
break;
}
}
while (loopcount<sanity);
}
}

Java swing jbutton charging old image

i created a custom Java Button like this
public class GraphicPaintedButton extends JButton implements ToPaint{
protected BufferedImage background;
private boolean painted = false;
public GraphicPaintedButton() {
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
if(painted){
System.out.println("PAINTING!");
Dimension size = getSize();
g.drawImage(background, 0, 0,size.width, size.height,0, 0, background.getWidth(), background.getHeight(), null);
}
}
#Override
public void loadImage(String url){
painted = true;
URL imagePath = getClass().getResource(url);
BufferedImage result = null;
try {
result = ImageIO.read(imagePath);
} catch (IOException | IllegalArgumentException e) {
System.err.println("Errore, immagine non trovata");
e.printStackTrace();
}
background = result;
}
}
Iif i load an image on the button, it calls the repaint,and it's good, the image is shown, when i load a new Image, it calls the repaint again and the new Image is shown. The problem is when i pass the mouse over the button, it calls the rapaint, but loads the old image. Why? And how did it get the old image, as the new one should have replaced it?
I don't know why you want to go this extend and not simply use the icon property of the button, but...
First, I'd get rid of the painted flag, it runs the risk of allowing the paintComponent method to try and paint a null image, because the loadImage method may fail, but the painted flag is always set to true - Let's face it, you could easily end up with painted == true and background == null ... which is not a valid state
Instead, reason about the actual state you're interested in...
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
if (background != null) {
Dimension size = getSize();
g.drawImage(background, 0, 0, size.width, size.height, 0, 0, background.getWidth(), background.getHeight(), null);
}
}
I would also change the loadImage method
public void loadImage(URL url) throws IOException {
background = ImageIO.read(url);
revalidate();
repaint();
}
First, don't use String, it's meaning is to ambiguous, instead, specify the lowest common parameter you're willing to deal with.
Secondly, the image is either going to load or it's not, if you're not going to deal with the exception, in any meaningful fashion, pass it back to the caller who may be in a better position to deal with it - IMHO
I don't know if this important or not, but I'd also consider overriding the getPreferredSize method...
#Override
public Dimension getPreferredSize() {
return background == null ? new Dimension(10, 10) : new Dimension(background.getWidth(), background.getHeight());
}
This will at least try and match the button's size to the size of the image

Adding an image in ActionListener [duplicate]

This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 6 years ago.
I am trying to make a JButton that displays an image in the JPanel when pressed - allowing the user to choose the location in the panel. I am using the following methods to paint:
public void paint(Graphics g, URL path) {
Image img = getImage(path);
Graphics2D g2 = (Graphics2D)g;
g2.drawImage(img, getX(),getY(),50,50, null);
}
public Image getImage(URL path) {
Image temp = null;
try
{
temp = Toolkit.getDefaultToolkit().getImage(path);
} catch (Exception e) {
e.printStackTrace();
}
return temp;
}
When I call paint(), I get a null pointer exception in my last line of my ActionListener:
dogButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
Graphics g = null;
Animal animal = new Animal();
animal.paint(g, main.class.getResource("/Animals/dog.jpg"));
}
I'm a little confused overall about how to use ActionListeners. This is my first project so I apologize for my lack of knowledge.
You have set
Graphics g = null;
Initialize g with something other than null.
I would recommend overriding public void paintComponent(Graphics g) of the JPanel where you plan to paint and use this graphics.

Recover the getSelectedValue from addMouseListener [duplicate]

This question already has answers here:
JList selected item to String - Weird result: Donnees.Marques#3d5bac58
(4 answers)
Closed 7 years ago.
In listMarques.addMouseListener, I would like to get the String in selectedCategories. I have tried this in my class,
Private selectedCategories = null
but it's not working.
listCategories.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent arg0) {
String selectedCategories = listMarques.getSelectedValue().toString();
System.out.println(selectedCategories);
}
});
listMarques.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent arg0) {
String selectedMarques = listMarques.getSelectedValue().toString();
if(selectedMarques != null && selectedCategories != null)
{
}
}
});
You are hiding the member variable with your local variable.
Replace
String selectedCategories = listMarques.getSelectedValue().toString();
with
YourClassName.this.selectedCategories = listMarques.getSelectedValue().toString();
where YourClassName would be the name of the class in which you are holding the member selectedCategories as well as the above code.
Good luck.

Categories

Resources