How to use variables of a method in the Mouse event class? - java

I have a code in javafx like this,
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
/**
*
* #author deb-l-ana
*/
public class NewFXMain extends Application {
#Override
public void start(Stage primaryStage) {
Group root=new Group();
Scene scene=new Scene(root,500,500,true);
int ctr=0;
Button b1=new Button("b1");
b1.setTranslateX(90);
root.getChildren().add(b1);
b1.setOnAction(e -> {
ctr=1;
});
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}
This gives me a compilation error
Local variables referenced from a lambda expression must be final or effectively final
But if I declare ctr as final I cannot modify it. What can I do so that I can modify a local variable from a lambda expression? But if I use an array, ctr1[]={0} with a single element and then I could reference it from the lambda expression and this works fine.
Why is this happening and how can I update the value of ctr from a mouse click event?

I can't explain better than him : https://stackoverflow.com/a/12750186/5677103
"An Integer is immutable [...] but you can design your own class to embed an integer and use it instead of an Integer."
public class MutableInteger {
private int value;
public MutableInteger(int value) {
this.value = value;
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
}
An instance of a final object can't be modified, but his attributes can be. Moreover, int is a privitive type and Integer an object that wraps this type.

Related

JavaFX ChoiceBox - How can you update the text of the popup items?

I have a ChoiceBox where I can select the language for my program. When I select another language, the label gets translated as desired (because it is recomputed using ChoiceBoxSkin#getDisplayText and my StringConverter takes the language into account), but the elements in the popup list stay the same.
Now, I could do something like
public void updateStrings() {
var converter = getConverter();
setConverter(null);
setConverter(converter);
var selected = valueProperty().getValue();
valueProperty().setValue(null);
valueProperty().setValue(selected);
}
in my ChoiceBox-subclass. This will re-populate the popup list with the correctly translated texts. Setting the value again is necessary beacause ChoiceBoxSkin#updatePopupItems (which is triggered when changing the converter) also resets the toggleGroup. That means that the selected item would no longer be marked as selected in the popup list.
Despite being kind of ugly, this actually works for my current use case. However, it breaks if any listener of the valueProperty does something problematic on either setting it to null or selecting the desired item a second time.
Am I missing a cleaner or just all-around better way to achieve this?
Another approach might be to use a custom ChoiceBoxSkin. Extending that, I'd have access to ChoiceBoxSkin#getChoiceBoxPopup (although that is commented with "Test only purpose") and could actually bind the text properties of the RadioMenuItems to the corresponding translated StringProperty. But that breaks as soon as ChoiceBoxSkin#updatePopupItems is triggered from anywhere else...
A MRP should be:
import javafx.scene.control.ChoiceBox;
import javafx.util.StringConverter;
public class LabelChangeChoiceBox extends ChoiceBox<String> {
private boolean duringUpdate = false;
public LabelChangeChoiceBox() {
getItems().addAll("A", "B", "C");
setConverter(new StringConverter<>() {
#Override
public String toString(String item) {
return item + " selected:" + valueProperty().getValue();
}
#Override
public String fromString(String unused) {
throw new UnsupportedOperationException();
}
});
valueProperty().addListener((observable, oldValue, newValue) -> {
if(duringUpdate) {
return;
}
duringUpdate = true;
updateStrings();
duringUpdate = false;
});
}
public void updateStrings() {
var converter = getConverter();
setConverter(null);
setConverter(converter);
var selected = valueProperty().getValue();
valueProperty().setValue(null);
valueProperty().setValue(selected);
}
}
And an Application-class like
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.stage.Stage;
import ui.LabelChangeChoiceBox;
public class Launcher extends Application {
#Override
public void start(Stage stage) {
Scene scene = new Scene(new LabelChangeChoiceBox());
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch();
}
}
This works but needs the duringUpdate variable and can break if there is another change listener.
I’m not sure if this meets your needs, as your description of the problem is unclear in a few places.
Here’s a ChoiceBox which updates its converter using its own chosen language, and also retains its value when that change occurs:
import java.util.Locale;
import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.geometry.Insets;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.control.ChoiceBox;
import javafx.scene.layout.BorderPane;
import javafx.util.StringConverter;
public class FXLocaleSelector
extends Application {
#Override
public void start(Stage stage) {
ChoiceBox<Locale> choiceBox = new ChoiceBox<>();
choiceBox.getItems().addAll(
Locale.ENGLISH,
Locale.FRENCH,
Locale.GERMAN,
Locale.ITALIAN,
Locale.CHINESE,
Locale.JAPANESE,
Locale.KOREAN
);
choiceBox.converterProperty().bind(
Bindings.createObjectBinding(
() -> createConverter(choiceBox.getValue()),
choiceBox.valueProperty()));
BorderPane pane = new BorderPane(choiceBox);
pane.setPadding(new Insets(40));
stage.setScene(new Scene(pane));
stage.setTitle("Locale Selector");
stage.show();
}
private StringConverter<Locale> createConverter(Locale locale) {
Locale conversionLocale =
(locale != null ? locale : Locale.getDefault());
return new StringConverter<Locale>() {
#Override
public String toString(Locale value) {
if (value != null) {
return value.getDisplayName(conversionLocale);
} else {
return "";
}
}
#Override
public Locale fromString(String s) {
return null;
}
};
}
public static void main(String[] args) {
launch(FXLocaleSelector.class, args);
}
}
Not entirely certain whether or not I understand your requirement correctly, my assumptions:
there's a ChoiceBox which contains the "language" for your ui, including the itself: lets say it contains the items Locale.ENGLISH and Locale.GERMAN, the visual representation of its items should be "English", "German" if its value is Locale.ENGLISH and "Englisch", "Deutsch" if its value is Locale.GERMAN
the visual representation is done by a StringConverter configurable with the value
If so, the solution is in separating out concerns - actually, it's not: the problem described (and hacked!) in the question is JDK-8088507: setting the converter doesn't update the selection of the menu items in the drop down. One hack is as bad or good as another, my personal preferenced would go for a custom skin which
adds a change listener to the converter property
reflectively calls updateSelection
Something like:
public static class MyChoiceBoxSkin<T> extends ChoiceBoxSkin<T> {
public MyChoiceBoxSkin(ChoiceBox<T> control) {
super(control);
registerChangeListener(control.converterProperty(), e -> {
// my local reflection helper, use your own
FXUtils.invokeMethod(ChoiceBoxSkin.class, this, "updateSelection");
});
}
}
Note: the hacks - this nor the OP's solution - do not solve the missing offset of the popup on first opening (initially or after selecting an item in the popup).
Not a solution to the question, just one way to have a value-dependent converter ;)
have a StringConverter with a fixed value (for simplicity) for conversion
have a converter controller having that a property with that value and a second property with a converter configured with the value: make sure the converter is replaced on change of the value
bind the controller's value to the box' value and the box' converter to the controller's converter
In (very raw) code:
public static class LanguageConverter<T> extends StringConverter<T> {
private T currentLanguage;
public LanguageConverter(T language) {
currentLanguage = language;
}
#Override
public String toString(T object) {
Object value = currentLanguage;
return "" + object + (value != null ? value : "");
}
#Override
public T fromString(String string) {
return null;
}
}
public static class LanguageController<T> {
private ObjectProperty<StringConverter<T>> currentConverter = new SimpleObjectProperty<>();
private ObjectProperty<T> currentValue = new SimpleObjectProperty<>() {
#Override
protected void invalidated() {
currentConverter.set(new LanguageConverter<>(get()));
}
};
}
Usage:
ChoiceBox<String> box = new ChoiceBox<>();
box.getItems().addAll("A", "B", "C");
box.getSelectionModel().selectFirst();
LanguageController<String> controller = new LanguageController<>();
controller.currentValue.bind(box.valueProperty());
box.converterProperty().bind(controller.currentConverter);

Can't compile Oracle docs example

this is my first question here so bear with me please.
I'm trying to use the Oracle Java docs, but when I try to compile example 6 on this page it doesn't work. I've tried everything I can think of. It's an old example, so that may be the issue, but it's disheartening that I can't figure out what should be a minor problem.
Example 6 Using an InvalidationListener
package bindingdemo;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.beans.binding.NumberBinding;
import javafx.beans.binding.Bindings;
import javafx.beans.InvalidationListener;
import javafx.beans.Observable;
class Bill {
// Define the property
private DoubleProperty amountDue = new SimpleDoubleProperty();
// Define a getter for the property's value
public final double getAmountDue(){return amountDue.get();}
// Define a setter for the property's value
public final void setAmountDue(double value){amountDue.set(value);}
// Define a getter for the property itself
public DoubleProperty amountDueProperty() {return amountDue;}
}
public class Main {
public static void main(String[] args) {
Bill bill1 = new Bill();
Bill bill2 = new Bill();
Bill bill3 = new Bill();
NumberBinding total = Bindings.add(bill1.amountDueProperty().add(bill2.amountDueProperty()),
bill3.amountDueProperty());
total.addListener(new InvalidationListener() {
#Override public void invalidated(Observable o) {
System.out.println("The binding is now invalid.");
}
});
// First call makes the binding invalid
bill1.setAmountDue(200.00);
// The binding is now invalid
bill2.setAmountDue(100.00);
bill3.setAmountDue(75.00);
// Make the binding valid...
System.out.println(total.getValue());
// Make invalid...
bill3.setAmountDue(150.00);
// Make valid...
System.out.println(total.getValue());
}
}
Thanks

Cannot instantiate ObservableList with an extractor

I have a custom object FermentableInRecipe, which populates a TableView. In order to respond to changes to items in the list, as well as the list itself, I have decided to employ an extractor. Here is my declaration and instantiation of my ObservableList:
private ObservableList<FermentableInRecipe> fermentablesInRecipe =
FXCollections.observableArrayList(item -> new Observable[]{item.WeightProperty()});
Here are the relevant segments of my custom class:
public class FermentableInRecipe {
private DoubleProperty weight;
...
public Double getWeight() {
return this.weight.getValue();
}
public void setWeight(Double value) {
this.weight.setValue(value);
}
public DoubleProperty WeightProperty() {
if (weight == null) {
weight = new SimpleDoubleProperty(0.0);
}
return weight;
}
...
}
In the links I've provided below, this approach worked. But Netbeans is telling me "DoubleProperty cannot be converted to Observable". I can see why this is the case, but I cannot understand why it worked in the links below and not for me, and how I should create extractor and link it to the weightProperty() function if this approach doesn't work.
Links:
JavaFX 2.0 Choice Box Issue. How to update a choiceBox, which represents a list of objects, when an object is updated?
JavaFX, ObservableList: How to fire an InvalidationListener whenever an object of the list gets modified?
Thanks in advance. Let me know if I've missed any crucial information.
There's nothing wrong with your code as written, this compiles just fine for me:
import javafx.application.Application;
import javafx.beans.Observable;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.stage.Stage;
public class JavaFXApplication1 extends Application {
class FermentableInRecipe {
private DoubleProperty weight;
public Double getWeight() {
return this.weight.getValue();
}
public void setWeight(Double value) {
this.weight.setValue(value);
}
public DoubleProperty WeightProperty() {
if (weight == null) {
weight = new SimpleDoubleProperty(0.0);
}
return weight;
}
}
private ObservableList<FermentableInRecipe> fermentablesInRecipe = FXCollections.observableArrayList(item -> new Observable[]{item.WeightProperty()});
#Override
public void start(Stage primaryStage) throws Exception {
}
}
I'd suggest double checking imports, and make sure you haven't imported java.util.Observable or similar by mistake.

Calling a Method That Takes a Parameter Within ActionListener

I've encountered a problem while trying to call a method within a class that implements actionListener. The method being called, DataCompiler, needs to use the integer wordCountWhole, which is returned in the wordCount class. The problem is that I can't pass the required parameter to the actionListener method.
import javax.swing.*;
import java.awt.*;
import java.awt.List;
import java.awt.event.*;
import java.beans.PropertyChangeListener;
import java.text.BreakIterator;
import java.util.*;
import java.util.stream.IntStream;
public class GUI extends JFrame {
public JTextArea textInput;
public JButton dataButton;
public String str;
public GUI() {
super("Text Miner");
pack();
setLayout(null);
dataButton = new JButton("View Data"); //Button to take user to data table
dataButton.setSize(new Dimension(120, 50));
dataButton.setLocation(5, 5);
Handler event = new Handler(); //Adds an action listener to each button
dataButton.addActionListener(event);
add(dataButton);
public class wordCount {
public int miner() {
//This returns an integer called wordCountWhole
}
}
public class Handler implements Action { //All the possible actions for when an action is observed
public void action(ActionEvent event, int wordCountWhole) {
if (event.getSource() == graphButton) {
Graphs g = new Graphs();
g.Graphs();
} else if (event.getSource() == dataButton) {
DataCompiler dc = new DataCompiler();
dc.Data(wordCountWhole);
} else if (event.getSource() == enterButton) {
wordCount wc = new wordCount();
sentenceCount sc = new sentenceCount();
wc.miner();
sc.miner();
}
}
}
}
And here's the code for the DataCompiler class:
public class DataCompiler{
public void Data(int wordCountWhole){
int m = wordCountWhole;
System.out.println(m);
}
}
You don't add the parameter there because you've invalidated the contract of the interface.
Use a constructor* (see note below, first)
public class Handler implements Action{ //All the possible actions for when an action is observed
private int wordCountWhole;
public Handler(int number) { this.wordCountWhole = number; }
#Override
public void actionPerformed(ActionEvent event) {
Although, it isn't entirely clear why you need that number. Your DataCompiler.Data method just prints the number passed into it, and that variable seemingly comes from nowhere in your code because it is not passed to the ActionListener.
* You should instead use Integer.parseInt(textInput.getText().trim()) inside Handler class / the listener code and not use a constructor. Otherwise, you'd always get the number value when you add the Handler, which would be an empty string and throw an error because the text area has no number in it.
Additionally, wc.miner(); returns a value, but calling it on its own without assigning it to a number just throws away that return value.

Deeplearning on Spark pipeline: How to predict using a neural network model in a pipeline?

I am trying to add sentiment analysis program to Spark pipeline. When doing it, I have class which extends org.apache.spark.ml.PredictionModel. When extending this PredictionModel class, I have to override predict() method which predicts the label for given feature. But, I get either 0 or 1 all the time when I execute this code.For example, if there are 10 movie reviews, five are negative reviews and other five are negative, it classifies all reviews as negative. I have attached the code below.
import org.apache.spark.ml.PredictionModel;
import org.apache.spark.ml.param.ParamMap;
import org.apache.spark.mllib.linalg.DenseVector;
import org.apache.spark.mllib.linalg.Vector;
import org.deeplearning4j.nn.multilayer.MultiLayerNetwork;
import org.nd4j.linalg.api.buffer.DataBuffer;
import org.nd4j.linalg.api.ndarray.INDArray;
import org.nd4j.linalg.factory.Nd4j;
import java.io.*;
//Model produced by a ProbabilisticClassifier
public class MovieReviewClassifierModel extends PredictionModel<Object, MovieReviewClassifierModel> implements Serializable{
private static final long serialVersionUID = 1L;
private MultiLayerNetwork net;
MovieReviewClassifierModel (MultiLayerNetwork net) throws Exception {
this.net=net;
}
#Override
public MovieReviewClassifierModel copy(ParamMap args0) {
return null;
}
#Override
public String uid() {
return "MovieReviewClassifierModel";
}
public double raw2prediction(Vector rawPrediction) {//Given a vector of raw predictions, select the predicted label
return rawPrediction.toArray()[0];
}
#Override
public double predict(Object o) {
int prediction=0;
DenseVector v=(DenseVector)o;
double[] a=v.toArray();
INDArray arr=Nd4j.create(a);
INDArray array= net.output(arr,false);
DataBuffer ob = array.data();
double[] d=ob.asDouble();
double zeroProbability=d[0];
double oneProbability=d[1];
if (zeroProbability > oneProbability) {
prediction=0;
}
else{
prediction=1;
}
return prediction;
}
}
Can you give me reasons for the wrong predictions?
In public double predict(Object o) you have a following if statement:
if (zeroProbability > oneProbability) {
prediction=0;
}
else{
prediction=1;
}
which causes the return of 0 or 1. Change this method in order to have some other prediction values.

Categories