Why can't I call a class method with its object? - java

Gym.java
public class Gym extends ActiveObject {
public void run() {
...
}
}
GymController.java
public class GymController extends WindowController implements KeyListener{
private Gym gym;
public void begin() {
Gym gym = new gym(canvas, new Location(dx, dy), delay, this);
}
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
if (key == KeyEvent.VK_SPACE) {
gym.run();
}
}
}
There is an object and its moving code in Gym.java file... and I wanted to call that to GymController.java file's keyPressed method... so that the object moves when the user presses the space bar.
How do I even link these two files in the first place...?
But the compiler is giving me an error saying that it cannot find symbol.
How can I call a method from another .java file into current file's keyPressed method properly, so that it compiles...?

As pointed out by comments, your problem lies in:
public void begin() {
Gym gym = new gym(canvas, new Location(dx, dy), delay, this);
}
And it should be:
public void begin() {
gym = new Gym(canvas, new Location(dx, dy), delay, this);
}
First of all, new takes the class name, you are building an actual object from a "pattern". Then, doing Gym gym =... creates a local variable within the scope of your begin() method. It will be discarded on return from begin.
If you just use gym or this.gym, it will assign the new instance to the member variable.
But be careful, your initial gym instance will create a new gymcontroller instance which will, in turn create a new gym instance. So the gym.run() will not use the same instance of gym than the one who created it. If that was your intention, you need to pass the this reference from gym to gymcontroller.

Related

how to use a list in another class?

I want to create a list, add blocks to it and then use it in a BlockBreakEvent to check if the block is in the list and cancel the event if it's not. But I can't seem to create and add things in it any other way than in the actual event itself (which looks to me like it would create issues). The only thing that is working for me is creating the list in the event and adding blocks to it one by one which looks really messy compared to: creating the list in a separate class and just checking the list with if(Listname.contains(block)) does anyone know how I can achieve this? Whether its dependency injection, or whatever else. I just can't figure out how to put it to use.
Here's what I've tried and is currently working for me, but I believe it's theoretically incorrect:
public class Event implements Listener {
#EventHandler
public void onBreak(BlockBreakEvent e) {
List<Material> allowedblocks = new ArrayList<Material>();
allowedblocks.add(Material.STONE);
//repeat this 10-50 times for whatever item
Player p = e.getPlayer();
Material block = e.getBlock().getType();
if(allowedblocks.contains(block)){
p.sendMessage("Invalid block. Break cancelled");
e.setCancelled(true);
}else{
p.sendMessage("Valid Block");
}
}
}
You can make allowedBlocks List a class field and fill it with elements inside of the constructor.
public class YourClass {
private List<Material> allowedBlocks = new ArrayList<>();
public YourClass() {
allowedBlocks.add(Material.STONE);
//repeat this 10-50 times for whatever item
}
#EventHandler
public void onBreak(BlockBreakEvent e) {
Player p = e.getPlayer();
Material block = e.getBlock().getType();
if(allowedBlocks.contains(block)){
p.sendMessage("Valid Block");
} else {
p.sendMessage("Invalid block. Break cancelled");
e.setCancelled(true);
}
}
}
Another approach would be to make the list static and fill it with values inside of a static block. I would not recommend making the list static if you are planning to change its values, but if your allowed blocks are going to remain the same, it may be a good idea to even go further and make it public, so you can access it from anywhere without an instance of YourClass
public class YourClass {
public static final List<Material> allowedBlocks;
static {
List<Materials> list = new ArrayList<>();
list.add(Material.STONE);
//repeat this 10-50 times for whatever item
//use an unmodifiable list,
//so you do not accidentally change its content later
allowedBlocks = Collections.unmodifiableList(list);
}
#EventHandler
public void onBreak(BlockBreakEvent e) {
Player p = e.getPlayer();
Material block = e.getBlock().getType();
if(allowedBlocks.contains(block)){
p.sendMessage("Valid Block");
} else {
p.sendMessage("Invalid block. Break cancelled");
e.setCancelled(true);
}
}
}
In the first case, there will be a list of allowedBlocks per instance of YourClass, which means, that every time you call new YourClass() a new List will be created and filled. In the second case, there will be only one list which will be created and populated on class loading (at the very beginning of the program) start up.
P.S. I would rather use a Set instead of a List here, considering you are using contains very often.
Since you are using an enum to store your Material types, you can simply call the static .values() method through Material.
Ex:
#EventHandler
public void onBreak(BlockBreakEvent e) {
Player p = e.getPlayer();
Material block = e.getBlock().getType();
if(List.of(Material.values()).contains(block)){
p.sendMessage("Invalid block. Break cancelled");
e.setCancelled(true);
}else{
p.sendMessage("Valid Block");
}
}
}
If you need to be able to customize what values are in the List you can use the singleton pattern to access that information globally.
The instance can be accessed statically from anywhere in the application:
import java.util.List;
public class BlockController {
public static BlockController instance = new BlockController();
private List<Material> allowedBlocks;
public BlockController() {
this.allowedBlocks = new ArrayList<>();
}
public void addAllowedBlock(Material mat) {
this.allowedBlocks.add(mat);
}
public void removeAllowedBlock(Material mat) {
this.allowedBlocks.remove(mat);
}
public boolean containsBlock(Material mat) {
return this.allowedBlocks.contains(mat);
}
public void clear() {
this.allowedBlocks.clear();
}
/**
* You can add more functionality here...
* This class can be accessed anywhere in the application
*
* use:
*
* BlockController controller = BlockController.instance;
* controller.containsBlock(Material.BLOCK);
*/
}
One approach to creating the list in a separate class is to use a static initializer block:
public class MyClass {
public static final List<Material> ALLOWED_MATERIALS = new ArrayList<>();
static {
ALLOWED_MATERIALS.add( Material.STONE );
}
public static List<Material> getAllowedMaterials() {
return Collections.unmodifiableList( ALLOWED_MATERIALS );
}
...
}
Try to create the List in a static context. This way the list is the same for all instances:
public class MyClass {
public static List<Material> allowedblocks = new ArrayList<Material>();
#EventHandler
public void onBreak(BlockBreakEvent e) {
allowedblocks.add(Material.STONE);
...
Then you can call the List from everywhere like this (e.g. if statement):
if(MyClass.allowedblocks.contains(block))
Your problem seems similar to this question, maybe this answer helps too: .

How can I access a class other than though passing in a method?

Let us say we have a class called World. Which contains a class called Data. We also have a third class called Input. If Input.clicked(Event event, int x, int y) were to be called I would not be able to access World which means I can't access Data. How do you go about resolving this?
Another way to ask this might be: How can you access something in a method from another class that can't be changed when what you need to access is not final?
Sorry, I am having a hard time explaining this.
Update bit: The world class already exists, can't create a new one. It would be inside the Game class.
Here is a code example, not working code. More pseudo.
public class World {
Data data = new Data();
Input input = new Input();
public void update(float delta) {
input.getInput();
input.makeChangesBasedOnInput();
}
public void render(float delta) {
}
}
public class Data {
public int importantNumber; // Static is not an option
// For me I have to get a user name... but same idea here
public Data() {
Random ran = new Random();
importantNumber = ran.nextInt(1000);
}
}
public class Input {
Button button = new Button();
public Input() { // passing the World class does not work, ex. public Input(World world) {
button.addListener(new ClickListener() {
#Override
public void clicked(InputEvent event, float x, float y) { // I can't add world here...
// HERE IS ISSUE
System.out.println(World.Data.importantNumber);
}
}
}
public void getInput() {
// MAGIC
}
public void makeChangesBasedOnInput() {
// MAGIC
}
}
Update 2: Here is another example of what I am trying to do with TextButton & ClickListener from libgdx.
statsButton is a TextButton() from libgdx.
You say passing the World class does not work, well that is probably because you tried to acces a local variable from anonymous function, example:
public Input(World world) {
button.addListener(new ClickListener() {
#Override
public void clicked(InputEvent event, float x, float y) {
// error: world is not final
System.out.println(world.data.importantNumber);
}
}
}
this is what probably happened (if not, please let me know). In Java 8, world would be effectivly final, but in Java 7 or earlier, you would have to declare it final explicitly, like
public Input(final World world) { ... }
Also a common approach is to store your world inside a field:
private World world;
public Input(World world) {
this.world = world;
...
}

How to change jlabel text from another class

Hi I'm making an app but, I found a problem. I'm using netbeans gui builder to build my gui.
So, the first gui class has a lot of button(every button does the same function) that have an actionlistener that looks like this:
public class Guipanel extends JPanel {
private void jbtTTActionPerformed(java.awt.event.ActionEvent evt) {
if(mb.getlevel() > 16){
if(ttp != 20 && mb.getpoints() != 0){
point();
ttp++;
jbtTT.setText(""+ttp);
}
}
}
private void point(){
mb.reducepoints();
}
int ttp;
Base mb = new Base();
JButton jbtTT = new JButton();
}
The Base Class has a lot of method but the one that is related to this problem looks like this:
public class Base extends JFrame {
//point decrement method
public void reducepoints(){
points--;
jlbPoints.setText("Points Available: "+points);
}
//return point value
public int getpoints(){
return this.points;
}
//return level value
public int getlevel(){
return this.level;
}
private static int level = 1;
private static int points = 20;
private JLabel jlbPoints = new JLabel("Points Available: "+points);
}
So the problem is this, when I pressed the jbtTT the points variable will decrement so the value will change from 20 to 19. I used System.out.println to verify that. As you can see, the reducepoints() method should update the jlbPoints text which it doesnt. I have tried making the Base mb = new Base() to static Base mb = new Base() but it still doesn't work. Am I doing this wrong? Anyone have a suggestion?
EDIT: I've tried to do System.out.println(jlbPoints.getText()); and the text did changed. The only one that didn't change is the text that the user can see. Even repaint() and revalidate didn't work.
EDIT2: I finally found the answer to this question. I have to pass the 'Base' class object to the 'Guipanel' class since I created the 'Base' class object in a main class(I don't want to use this class as a main class). I passed it with the following method:
public void passObj(Base mb){
this.mb = mb;
}
and changing the constructor of 'Guipanel' class like this:
public Guipanel(Base mb) {
initComponents();
this.mb = mb;
}
also changing this Base mb = new Base(); to Base mb;
I wanted to thank everyone that have tried to answer this question.
Try using SwingUtilities.invokeLater() to ensure you are changing the text on the event dispatch thread, as you are supposed to. All we can do is guess given the current information.

Java Inheritance : 2nd instance calls 1st instance method

I have a very strange problem with a java class in my android application.
I have some sub classes which extend my abstract class GameDialog
GameDialog class
public abstract class GameDialog extends Sprite
{
private static boolean gd_visible = false;
protected GameDialog(GameScene scene, Camera camera, VertexBufferObjectManager pSpriteVertexBufferObject){
...
}
public boolean display(){
if(!GameDialog.gd_visible) {
...
}
}
protected boolean hide(){
if(GameDialog.gd_visible){
...
}
}
}
PauseDialog class
public class PauseDialog extends GameDialog {
public PauseDialog(GameScene scene, Camera camera, VertexBufferObjectManager pSpriteVertexBufferObject) {
super(scene, camera, pSpriteVertexBufferObject);
...
final ButtonSprite play_button = new ButtonSprite(...);
play_button.setOnClickListener(setPlayButtonListener());
}
private OnClickListener setPlayButtonListener() {
return new OnClickListener() {
#Override
public void onClick(ButtonSprite pButtonSprite, float pTouchAreaLocalX, float pTouchAreaLocalY) {
hide();
}
};
}
}
Each time I want to display a dialog, I write this line :
new PauseDialog(GameScene.this, camera, vbom).display();
The first time, it works well : the dialog is displayed, user make a choice and it's hidden.
But the 2nd time, the dialog is not hidden (after user's choice).
I used the debugger to see what's going on, and the conclusion is :
In the 2nd instance, it calls the hide() method of the first instance !
If some one can explain me what it is doing that ... Thank you.
It is because gd_visible is static. Delete the static keyword and it should work. Static fields doesn't belong to the instances but they belong to the class.

Java how and where to initialize variable with NullPointerException

I'm having a problem where I receive this error:
Exception in thread "main" java.lang.NullPointerException
at com.noxia.Main.startCombat(Main.java:101)
at com.noxia.Area1.createArea1Enemy(Area1.java:43)
at com.noxia.Main.main(Main.java:30)
I know that I need to initialize the variables because they are null, but I can't seem to figure out what I need to put where. I've minimized the code to show just the relevant parts as there are many other variables and methods left out, but this seems to pertain to the issue. Any help would be greatly appreciated =)
public class Main {
Player p;
Enemy e;
Area1 a1;
public static void main(String[] args) {
Main main = new Main();
main.a1 = new Area1();
main.p = new Player(100);
//the line directly below this is line 30 where the error occurs
main.a1.createArea1Enemy(10);
}
public void startCombat()
{
//the line directly below this is line 101 where the error occurs
while (p.getCurrentLife() > 0 & a1.e.getLife() > 0)
{
p.playerAttack();
if (p.getCurrentLife() > 0 & a1.e.getLife() > 0)
{
e.enemyAttack();
}
}
}
public class Player extends Main {
private int currentLife;
public int getCurrentLife()
{
return currentLife;
}
public void setCurrentLife(int cl)
{
currentLife = cl;
}
public Player(int cl)
{
currentLife = cl;
}
public class Enemy extends Main {
private int life;
public int getLife()
{
return life;
}
public void setLife(int lf)
{
life = lf;
}
public Enemy (inf lf)
{
life = lf;
}
public class Area1 extends Main {
public void createArea1Enemy(int enemyCounter)
{
while (enemyCounter > 0)
{
String[] enemyList = {"Enemy1", "Enemy2"} //code for Enemy2 left out below
int enemyListLength = enemyList.length;
int randomEnemy = (int) (Math.random() * enemyListLength);
if (enemyList[randomEnemy].equals("Enemy1"))
{
Enemy enemy1 = new Enemy("Enemy1", 100);
//the line directly below this is line 43 where the error occurs
startCombat();
}
enemyCounter--;
}
}
}
The simple answer is that you have to set e to an enemy before calling startCombat.
But a better way to do this would be to remove e, and pass the enemy object to startCombat using a method parameter. The e field is conceptually wrong. To understand the wrongness, try to come up with a coherent explanation of what it means in terms of the state of a Main object.
Clearly this is beginner code ... and there are a number of bad things about what you have written:
The fields of a class should be for object state, not for passing parameter values to methods.
You should avoid writing code that accesses the innards of a class ... like your main method does.
Best practice is to make fields private, and defined getter and / or setter methods (as required) for external classes to access / modify them.
You need to learn how to write constructors with parameters.
You need to design your code properly. Everything extending Main means that there is going to be no rational model of what the objects "mean". And there's the problem that each instance of Enemy and Area1 will have their own copies of the p, e, and a1 fields, and a whole bunch of inappropriate methods.
The main problem is that you never initialize Enemy e;. You create an enemy but never assign it to this.e.
Change this line:
Enemy enemy1 = new Enemy("Enemy1", 100);
To this:
this.e = new Enemy("Enemy1", 100);
There are also many other problems with your code.
Learn how to write a constructor properly. This code is wrong.
I see no reason at all why a Play, Area1, and Enemy should extend Main.

Categories