So, I'm pretty sure I did everything correctly, but when I run my program, it gives me this log:
Exception in thread "main" java.lang.NullPointerException
at com.BLANK.handler.ButtonHandler.<init>(ButtonHandler.java:19)
at com.BLANK.BLANKScreen.<init>(BLANKScreen.java:28)
at com.BLANK.BLANKWindow.<init>(BLANKWindow.java:28)
at com.BLANK.BLANKWindow.main(BLANKWindow.java:11)
Here's the code that's giving me errors in the ButtonHandler class:
public Button button;
public int buttonX = button.x;
public int buttonY = button.y;
public int buttonSizeX = button.xSize;
public int buttonSizeY = button.ySize;
And here's the button integers that it's referring to:
public int x;
public int y;
public int xSize;
public int ySize;
public Button(int x, int y, int xSize, int ySize, String s, Graphics g) {
this.x = x;
this.y = y;
this.xSize = xSize;
this.ySize = ySize;
}
Anyone have any ideas as to what I am doing wrong and how I could fix it?
P.S. If you need any more code snippets just tell me and I'll provide them.
Problem
When you declare this:
public Button button;
public int buttonX = button.x;
You are creating and initializing the fields of a class:
button does not have any initialization, so it defaults to null
buttonX is supposed to be assigned button.x, but this expression is trying to get the field of a null object, which causes NPE (this is the very meaning of this exception)
Solution
The direct solution would be to initialize button before declaring the other fields. But from what I see you'd rather not use fields to "store" button.x. Use button.x directly where needed.
You're declaring a Button:
public Button button;
and without initializing it you're trying to assign:
public int buttonX = button.x;
which gives you NPE because button is still null
If this
public Button button;
public int buttonX = button.x;
public int buttonY = button.y;
public int buttonSizeX = button.xSize;
public int buttonSizeY = button.ySize;
is a consecutive code block and there are no lines of code between these, then your code can't work.
You declare a new variable button. This variable will be initialized with null by default. After that you try to access a property of that variable which is null at this point. This causes your NullPointerException.
To have accurate access to a property you need to initialize the variable correctly.
public Button button = new Button(x, y, xSize, ySize, string, graphics);
You need to initialize a variable before you use it ...
By doing this you will get an null pointer
public Button button;
public int buttonX = button.x;
Because button is not initialized yet.
button is null and you get a null pointer when you try to perform some action on an object which is null.
Related
SOLVED: The set setRoomImage method was never called on the RoomTile Object. Thanks to #sorifiend for noticing this!
I currently place JLabels using this method:
public void spawnItem(Entity e, int x, int y, int i, int j) {
bgLabel[i][j] = new JLabel();
bgLabel[i][j].setBounds(x,y,e.width,e.height);
bgLabel[i][j].setIcon(e.sprite);
layeredPane.add(bgLabel[i][j], e.layer);
}
Where bgLabel[][] is an array of JLabels and e.sprite is an imageIcon as shown in the Entity Class below. As well, e.layer is the appropriate Integer (i.e. 0, 100, 200).
The Entity Class looks like this:
import javax.swing.*;
public class Entity {
public int width, height;
ImageIcon sprite;
Integer layer;
}
And I extend the entity class like this:
import java.net.URL;
public class RoomTile extends Entity{
boolean light;
public RoomTile(boolean isLight) {
height = 52;
width = 52;
layer = 0;
light = isLight;
}
public void setRoomImage(String s) {
URL url;
if (light) {
url = getClass().getResource("Assets/" + s + ".png");
} else {
url = getClass().getResource("Assets/Dark" + s + ".png");
}
sprite = new ImageIcon(url);
}
}
All JLabels are placed by nested for loop iterating over a 2d array, the object is then added to the layered pane using the spawnItem method. This all works properly and a grid of objects, such as rooms, are placed and visible. However, when attempting to change the icon of these JLabels, they simply disappear.
I am using the method setLight to receive the label that is desired to be changed:
public void setLight(int i, int j) {
RoomTile lightRoom = new RoomTile(true);
bgLabel[i][j].setIcon(lightRoom.sprite);
repaint();
revalidate();
}
The setLight method is within a class which extends JFrame.
When setLight is called, the JLabel at the grid position provided, simply disappears, rather than its icon changing. I'm not sure where I've gone wrong and any help would be greatly appreciated.
I am designing my own clickListener class. When i touch down on any actor registered with my clicklistener, i would like to pause all the actions on the actor, and only call it back when touch up is trigger. I tried with the following codes but it give me a total hang everytime i triggered touchUp.
public class MyClickListener extends ClickListener {
public Actor actor;
Array<Action> cachedActions;
#Override
public void touchUp(InputEvent event, float x, float y, int pointer, int button) {
super.touchUp(event, x, y, pointer, button);
actor = event.getListenerActor();
actor.addAction(btnScaleBackActions());
for(Action a: cachedActions)
{
a.reset();
a.setTarget(actor);
a.setActor(actor);
actor.addAction(a); //this line give me a total hang
}
}
#Override
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
if(pointer==0) // avoid further trigger on other buttons while holding the selected actor
{
actor = event.getListenerActor();
actor.setScale(0.9f);
cachedActions = actor.getActions();
actor.clearActions();
if(autoSetSound)AudioManager.playSound(AudioManager.CLICK_IN);
return super.touchDown(event, x, y, pointer, button);
}
else
{
return false;
}
}
public static Action btnScaleBackActions(){
float time = 0.1f;
return sequence(
scaleTo(1,1,time ),
scaleTo(0.95f,0.95f,time/4),
scaleTo(1,1,time/4)
);
}
}
It shows no error but only white screen. Any help?
The problem is this line:
cachedActions = actor.getActions();
You are getting a reference to the Actor's own list of actions instead of making a copy. Incidentally, on the next line (actor.clearActions();) you are clearing the list so cachedActions is empty.
Later on touch up, the actor (and cachedActions) now have the action you added (btnScaleBackActions()). You are cycling through an array, adding the same object to it forever. The iterator can never finish because you are always adding more, so it is an infinite loop.
You need to create your own list for cached actions and copy the items over.
private final Array<Action> cachedActions = new Array<Action>();
Then copy the actions, not the reference in touch down:
cachedActions.addAll(actor.getActions());
actor.clearActions();
And make sure to clear cachedActions at the end of touchUp.
I have a frame that contains 81 buttons, lets say all the buttons contain no name, are all equal in size, and are all set automatically. So when I click one I would like to know which one is clicked. If I use a class that implements MouseListener and with this method
mouseClicked(MouseEvent e){
temp[0]= e.getX();
temp[1]= e.getY();
}
How can I check with these coordinates?
Do I have to set each of the buttons with its own location to do that?
I believe this is what you are looking for.
public static final int BUTTONS_WIDTH_COUNT = 9;
public static final int BUTTONS_HEIGHT_COUNT = 9;
public static final Button[][] BUTTONS = new Button[BUTTONS_WIDTH_COUNT][BUTTONS_HEIGHT_COUNT]
...
// I'll assume that the buttons are taking up the entire frame so no offsets are taken into account
frame.addMouseListener(
new MouseAdaptor() {
mouseClicked(MouseEvent e) {
// The X Y coordinates are relative to the component so
int frameWidth = frame.getBounds().getWidth();
int frameHeight = frame.getBounds().getHeight();
Button buttonClicked = buttons[e.getX()/(frameWidth/BUTTONS_WIDTH_COUNT)][e.getY()/(frameHeight/BUTTONS_HEIGHT_COUNT)];
}
}
EDIT: Actually it will be a lot better to assign the same MouseAdaptor to all the buttons and use e.getSource() to know which button was invoking in the listener.
I have 5 button and a want each button can't print number 1,2,3,4,5. but each button only print "5". Is there any wrong with my code? Or its bug on libgdx? I use libgdx v1.2.0
for (Integer i = 1; i <=5 ; i++){
tabeldalam=new Table(skin);
tabeldalam.row();
tabeldalam.add(new Label("GAmbar :", skin)).height(100).width(100);
tabeldalam.row();
tabeldalam.add(new Label("Harga",skin)).height(30).width(100);
tabeldalam.row();
TextButton nextbutton = new TextButton("Beli",skin);
nextbutton.setWidth(100);
nextbutton.setHeight(20);
nextbutton.addListener(new ClickListener() {
#Override
public void clicked(InputEvent event, float x, float y) {
beli(i);
}
});
tabeldalam.add(nextbutton).height(20).width(100);
tabelLuar= new Table(skin);
tabelLuar.add(tabeldalam).width(100).height(150);
}
private void beli(Integer i){
text2.setText(i.toString());
}
Use int instead of Integer for your for loop. All of your click listeners are referencing the same instance of Integer because it is an object and not a primitive.
For code non-ambiguity I would copy the variable to a final int variable and use that for the click listener so it is absolutely clear that a separate int is used for each.
final int index = i;
...
//use index in the ClickListener instead of i
try this simple example:
...// Change in your Code addListener for this:
nextbutton.addListener(new ClickListenerOverflow(i) {
#Override
public void clicked(InputEvent event, float x, float y) {
beli(n);
}
});
...//
Add this code inside of your Class:
private class ClickListenerOverflow extends ClickListener{
int n;
public ClickListenerOverflow(int n){
this.n = n;
}
}
when you click call beli (i), i then its value is 5, it is the latter who won the for.
Hi im having trouble with how to user the super() keyword properly. It's a bit difficult to explain so please try to understand.
So I have a class called "Window" which is a subclass of another class called "Room".
This is Room class with a constructor
public class Room {
private Position position;
private Color color;
public Room(Position pos, Color colour){
this.position = pos;
this.color = color;
}
}
SO I want to give the doors a color Color.RED A Window object is constructed with an input position parameter.
What I have so far is:
public class Window extends Room{
private Color color;
public Window(Position position, Color color) {
super(position, color);
this.colour = Color.RED;
}
However in my other classes there is code that create a new Window with only a position parameter
This is example code
public class example{
private Window window;
private Position position;
public example() {
}
#Before
public void create() {
position = new Position(4,3);
window = new Window(position);
}
So then it becomes a required and found error, telling me that the length is not right. I understand what the error is telling me.
So here is my question. How do I redo the Window constructor so that it will satisfy both the super class and my other classes without those classes being changed.
Create new constructor in Window and set default color.
public Window(Position position) {
//Set default color
super(position, Color.RED);
this.colour = Color.RED;
}
Add another constructor to your Window class:
public class Window extends Room {
public Window(Position position) {
super(position, null);
}
Alternatively, define a default color which gets passed instead of null.