Final variable being changed without any = statements - java

I'm making an autoclicking project in java for personal use, and using the following method to get coordinates of a click from a class that extends MouseAdapter. The click is being done on a JFrame.
int[] mouseCoordinates = new int[2]; //The coordinates of the click
mouseCoordinates = mouseListenerExample.getCoordinates();
final int[] baseCoordinates = mouseCoordinates; //The base coordinates (no click) which is this problem//
int[][] totalCoordinates = new int[4][2]; //An array that collects all coordinates of 4 mouse clicks
for (int i = 0; i < 4; i++){ //the goal is to get the coordinates of 4 clicks
while (mouseCoordinates[0] == baseCoordinates[0]){
mouseCoordinates = mouseListenerExample.getCoordinates(); //The problem occurs here: when mouseListenerExample.getCoordinates() changes, mouseCoordinates is changed, baseCoordinates is also changing, which it shouldnt, since there are no statements that say so.
if (mouseCoordinates[0] != baseCoordinates[0]) {
break;
}
}
totalCoordinates[i] = mouseListenerExample.getCoordinates();
mouseListenerExample.setCoordinates(baseCoordinates);
mouseCoordinates = baseCoordinates;
}
Is there some statement that is changing baseCoordinates that I am missing?

Your baseCoordinates variable has been declared final, and so it cannot change, but since it is an int[] or int-array, it is a reference variable, and so what cannot change is the reference itself, not the state of the reference, and so the ints held within the array can (and in your case -- do) change.
You're changing the values held by mouseCoordinates. Since the baseCoordinates refers to the exact same int[] object, then this will likewise change the values for baseCoordinates. Best to create a completely new int object for the final variable if you don't want it changed.
Do something like:
final int[] baseCoordinates = new int[mouseCoordinates.length];
System.arraycopy( mouseCoordinates, 0, baseCoordinates , 0, mouseCoordinates.length );

So after some looking around, i just replaced the arrays with individual ints, and added a print statement right before the break, and it made it work.

Related

Is there any other way to implement setOnMouseClicked on JavaFX

I had to create a matrix in javaFX. I created it without any problem with GridPane. The next thing is to create like "buttons" on the right side of the matrix, these buttons will move +1 element of the matrix to the right. Like this:
110 <-
101 <- //ie: I clicked this button
100 <-
The result:
110 <-
110 <-
100 <-
The way I handle this bit-shifting-moving was with circular linked list. I don't have any problem with that I think you can ommit that part. I use this method:
private void moveRowRight(int index){
//recives a index row and moves +1 the elements of that row in the matrix.
}
cells is the matrix
The problem is that, first the matrix can be modified by the user input i.e. 5x5 6x6 7x7, so the number of buttons will also change. I tried using a BorderPane(center: gridpane(matrix), right: VBox()) and this is the part of the code how I added some HBox inside the Vbox (right part of the border pane) and using the setOnMouseClicked.
private void loadButtonsRight(){
for(int i = 0; i < cells[0].length ; i++){
HBox newBox = new HBox();
newBox.getChildren().add(new Text("MOVE"));
newBox.prefHeight(50);
newBox.prefWidth(50);
newBox.setOnMouseClicked(e -> {
moveRowRight(i);
});
VBRightButtons.getChildren().add(newBox); //where I add the HBox to the VBox (right part of the Border Pane)
}
}
}
But then there's this problem.
Local variables referenced from lambda expression must be final or effectively final
It seems that I cannot implement lambda with a value that will change. Is there any way to help me to put "buttons" that depends of the matrix size and that uses the method I've created?
The message tells you all you need to know to fix the problem:
Local variables referenced from lambda expression must be final or effectively final
Assign your changing variable to a final constant and use the constant value in the lambda instead of the variable:
final int idx = i;
newBox.setOnMouseClicked(e ->
moveRowRight(idx);
);
If you wish to understand this more, see the baeldung tutorial
https://www.baeldung.com/java-lambda-effectively-final-local-variables

Fill ArrayList with colors for Android

I want to create 2 ArrayList. One holding 16 colors, the other one holding 139.
I have the list with colors (both RGB as 255,126,32 and Hex as 0xFFFF2552). I want to use the ArrayList to later pick random colors from.
I've tried int[], that doesn't work. I've tried ArrayList<Integer> and ArrayList<Color>. My problem is; I don't understand how to add the colors to the ArrayLists.
Thanks!!
For now, I'm exploring this:
Color cBlue = new Color(0,0,255);
Color cRed = new Color(255,0,0);
ArrayList colors = new ArrayList();
colors.add(cBlue);
colors.add(cRed);
and so on...
I really like int[] colors = = new int[] {4,5}; because it's only one line of code... but how do I get colors in, to later on, pick from?
or.. would it be better to store the colors in a strings.xml file and then fill the ArrayList from there? If so, how should I do that?
Thanks!!
You could try:
int[] colors = new int[] {Color.rgb(1,1,1), Color.rgb(...)};
For example, but I don't think it's a good idea to decide only using "one line" argument.
List<Integer> coloras = Arrays.asList(new Integer[]{Color.rgb(1, 1, 1), Color.rgb(...)});
Will also work.
You can create an arraylist in arrays.xml file:
<resources>
<string-array name="colors">
<item>#ff0000</item>
<item>#00ff00</item>
<item>#0000ff</item>
</string-array>
</resources>
Then use the loop to read them:
String[] colorsTxt = getApplicationContext().getResources().getStringArray(R.array.colors);
List<Integer> colors = new ArrayList<Integer>();
for (int i = 0; i < colorsTxt.length; i++) {
int newColor = Color.parseColor(colorsTxt[i]);
colors.add(newColor);
}
In my opinion keeping colors in the list is the most convinient solution.
To take a color from the list randomly, you do:
int rand = new Random().nextInt(colors.size());
Integer color = colors.get(rand);
I would make a text file or xml file populated with the color info and have a function that reads in each line of the file using a loop, creates a Color object for each line and adds it to the array list and then goes to the next line until there are no lines left.
I would recommend against using a configuration file unless you want to be able to change your colors without code changes. I suspect your colors are constant though, so the file would just add unnecessary complexity to your application.
The code sample in your question assumes java.awt.Color when you would actually use the utility class android.graphics.Color which cannot be instantiated.
Therefore I recommend the following solution as a static variable (and be careful not to modify the contents of the array later):
static final int[] colors16 = {
Color.rgb(255, 0, 0),
Color.rgb(0, 255, 0),
Color.rgb(0, 0, 255)
};
Now add a static instance of Random to use for selecting random colors from the list.
static final Random random = new Random();
And then pick your color!
int colorIndex = random.nextInt(colors16.size());
Color color = colors16.get(colorIndex);
If you feel it's important to protect the contents of your list, you can make it immutable as follows, at the small expense of boxing your color ints into Integer objects.
static final List<Integer> colors = Collections.unmodifiableList(
Arrays.asList(
Integer.valueOf(Color.rgb(255, 0, 0)),
Integer.valueOf(Color.rgb(0, 255, 0)),
Integer.valueOf(Color.rgb(0, 0, 255))
)
);
Technically you can leave out the Integer.valueOf() conversion in the above snippet and Java will autobox the ints.
You can also can use int[] colors = new int[]{color1.getRGB(),color2.getRGB()};
And decode using: Color color = new Color(colors[0]);
What you have looks like it makes sense, but you should specify the type of the ArrayList.
List<Color> colorList = new ArrayList<Color>();
colorList.add(cBlue);
... etc
(The difference between declaring it as a List or an ArrayList is that List is the interface that ArrayList implements. This is a generally pretty good practice, but for your purposes it probably won't make a difference if you declare it as a List or an ArrayList).
If you want to do it in fewer lines of code, you can use an ArrayList initializer block, like this:
List<Color> colorList = new ArrayList<Color> { new Color(...), cBlue };
Or with Arrays.asList, which takes in an array and returns a List.
But in general you should get used to verbosity with Java, don't try to optimize your lines of code so much as the performance of those lines.
(Sidenote: make sure you're using the correct Color class. There's android.graphics.Color and java.awt.Color, and they're totally different, incompatible types. The constructor you're using is from java.awt.Color, and with Android you're probably going to want to use android.graphics.Color).

android java array of paint

i am making a game and i trying to make bitmaps dissapear or appear anyway for some reason when i use paint as 1 object it works but when i add a array paint(fro each bitmap) it crashes
here is the lines i used with it:
//in MainActivity class
Paint[] paintanswer;
//in oncreate
paintanswer=new Paint[answerlength];
//in the draw func
for(int i=0;i<answerlength;i++){
paintanswer[i].setAlpha(answeralpha[i]);
canvas.drawBitmap(answerbitmapscaled[i],(float) (((cwidth/2)-((answerlength*answersize)/4)-answersize/4)+i*(answersize/2)),(float) (cwidth/2), paintanswer[i]);
the answer length is the length i get from other activity accordingly i set the array
An array in Java is just a container with a certain amount of slots for elements of a certain type. In your case a container that can store for example 20 Paint elements, however, it is completely empty. You have to fill the array with elements if you want to use them later on:
paintanswer = new Paint[answerlength];
for (int i = 0; i < answerlength; i++)
paintanswer[i] = new Paint();

wrong setting an arraylist

I want to ask a question about arraylist. In my program I defined an arraylist and an user defined object. The problem is when I want to add an object to this arraylist, it adds object, but next time when I give the different values to user object, it sets values of the old object that I added before to the new one. I mean, for example I have 13 in my old object and the new one is 14, it makes the old one 14. I couldn't find a solution for this. I'M working on a drawing program. I'm posting some parts of the code.
public class Tester extends JPanel implements MouseMotionListener, MouseListener {
ArrayList<Lines> array = new ArrayList<Lines>();
Lines l1;
...
public Tester(){
l1 = new Lines();
l1.point1 = new Point();
l1.point2 = new Point();
l1.denklem = new int[3];
And thi is how I add object into arraylist
else if(lineci == true){
if(mouseclicks == 0){
l1.point1.x = e.getX();
l1.point1.y = e.getY();
statusBar.setText( String.format( "Clicked at [%d, %d]",
e.getX(), e.getY() ) );
mouseclicks++;
starter = false;
}
else if(mouseclicks == 1){
l1.point2.x = e.getX();
l1.point2.y = e.getY();
statusBar.setText( String.format( "Clicked at [%d, %d]",
e.getX(), e.getY() ) );
mouseclicks = 0;
int a = l1.point2.y - l1.point1.y;
int b = l1.point1.x - l1.point2.x;
int c = (l1.point2.x * l1.point1.y) - (l1.point1.x * l1.point2.y);
l1.denklem[0] = a;
l1.denklem[1] = b;
l1.denklem[2] = c;
array.add(l1);
// array3.add(l1);
repaint();
}
}
When I click mouse, if lineci is true, it draws a line according to points. I get always last lines when I print elements of arraylist. If I draw 10 lines, 10 elements of the arraylist are the same. It never keeps old values inside arraylist. By the way boolean starter is not important. I just forget to remove it.
You are simply adding the same object repeatedly to the list. Each addition to the list is merely adding a reference to the same object: l1. Hence, when you update the state of l1, the old "object" also appears to have changed.
To rectify this you need to create a new instance of Lines for each addition you wish to perform.
You're referencing the original l1 object, so it will modify the original l1 object--whether or not it's in the list.
If you want to create a new object, create a new object.
i think your l1 reference is still pointing the previous object added to the arrayList , you should override the reference as soon as you add the object to the arraylist .
by either
l1 = new Lines();
or
l1 = null;
Use l1.clone() before changing the value inside if you want to keep all values same but one and the class is clonable or create a new object which is better for your case.

Null Pointer Exception on a 2D array (Java)

I have a class, "Tetris", in which one of the instance variables is "board". "board" is 2D array of Color objects. Upon the creation of a tetris object I call a method that sets the dimensions of board and then sets all of the Color objects to be the Default value, that is to say, Color.blue.
public Tetris(int rows, int cols) {
this.rows = rows;
this.cols = cols;
reset(rows, cols);
}
public void reset(int rows, int cols) {
Color[][] board = new Color[rows][cols];
for(int i = 0; i<this.rows; i++) {
for(int j = 0; j<this.cols; j++) {
board[i][j] = DEFAULT_COLOR; // Color.blue; //DEFAULT-COLOR
}
}
}
Unfortunately, when I run the code (which obviously has not been posted in its entirety) I get a null pointer exception on the line:
board[i][j] = DEFAULT_COLOR; // Color.blue; //DEFAULT-COLOR.
Is there anything obviously wrong with what I am doing?
It would help if you would post a short but complete program which demonstrated the problem. The code you've posted isn't enough to throw an exception, but I can see how with a few changes it might.
In particular, it seems odd to me that you're declaring a new local variable within your reset method... and you also have an instance variable called board? I suspect the solution may be as simple as changing the start of reset to:
board = new Color[rows][cols];
If your real code uses the local variable to create the array, but then tries to assign values via the instance variable, that could very well be the cause of the problem.
It also seems wrong that you're passing rows and cols into the method, and using those parameters in one place but the instance variables this.rows and this.cols in the loop. Why bother passing them at all?
I think you must allocate every one of those colors like this:
board[i][j] = new Color(...

Categories

Resources