JavaFX TextField listener - java

I need some help. I have an ArrayList of Textfields.
static List<TextField> lfLetters = new ArrayList<>();
And I want to check if the value has changed. And if it was I want to know which textfield it was. I know I can do this with a Listener but that only worked for a single one.
TextField textField = new TextField();
textField.textProperty().addListener((observable, oldValue, newValue) -> {
System.out.println("textfield changed from " + oldValue + " to " + newValue);
});
I want it to work on an Array and determine which textfield has changed.
Thanks in advance!

You can use ObservableList with appropriate extractor and add listener directly to list. This way it will be automatically watching changes in the specified properties of its elements. It is more convenient, than adding listener to each text field, but in this case you can't get old value:
ObservableList<TextField> oList =
FXCollections.observableArrayList(tf -> new Observable[]{tf.textProperty()});
oList.addListener((ListChangeListener.Change<? extends TextField> c) -> {
while (c.next()) {
if (c.wasUpdated()) {
for (int i = c.getFrom(); i < c.getTo(); ++i) {
System.out.println("Updated index: " + i + ", new value: " + c.getList().get(i).getText());
}
}
}
});

I was thinking that I will mark this quesiton as a duplicate, as you have a totally similar question here.
But in the end, you want to have the reference to the TextField also in the listener, so I will add an answer.
This snippet adds 10 TextField objects to the ArrayList and adds a listener to each.
for (int i = 0; i < 10; i++) {
TextField tf = new TextField();
final int index = i;
tf.textProperty().addListener((obs, oldVal, newVal) -> {
System.out.println("Text of Textfield on index " + index + " changed from " + oldVal
+ " to " + newVal);
});
lfLetters.add(tf);
}
Or if your ArrayList is already initialized, you can iterate through it simply:
lfLetters.forEach(tf -> {
tf.textProperty().addListener((obs, oldVal, newVal) -> {
System.out.println("Text of Textfield on index " + lfLetters.indexOf(tf) + " changed from " + oldVal
+ " to " + newVal);
});
});
Sample output
Text of Textfield on index 2 changed from InitialText - 2 to ModifiedText - 2
Text of Textfield on index 6 changed from InitialText - 6 to ModifiedText - 6

Related

Adding an individual array list item to individual tile

I am currently trying to place individual items within an array list into individual tiles within a inventory GUI. All the tiles are set up and I can display each array list item individually within the console line.
This is the simple GUI:
This is my attempt so far.
HBox itemTile[] = new HBox[31];
for (int i = 0; i < 30; i++) {
Button deleteButton = new Button("Delete Item");
deleteButton.setOnAction((ActionEvent event) -> {
displayItems2(); //temp info to console - delete item code to be added
JOptionPane.showMessageDialog(null, "Item has been deleted", null, 1);
});
itemTile[i] = new HBox(new Label("Item: " + i + " "));
itemTile[i].setStyle("-fx-border-color: black;");
itemTile[i].setPadding(new Insets(5));
itemTile[i].getChildren().add(deleteButton);
itemTile[i].setAlignment(Pos.CENTER_LEFT);
itemTile[i].setStyle("-fx-background-color: #e5efff; -fx-border-color: black;");
this.getChildren().add(itemTile[i]);
}
}
private void displayItems2(){
this.getChildren().removeAll(this.getChildren());
displayInvStructure();
ArrayList<String> descs = InventoryManager.getInstance().getItemDescriptions();
for (int i = 0; i < descs.size(); i++) {
String retString = descs.get(i);
System.out.println("Array item is = " + " " + i + " " + retString);
}
//If i = itemTile[i]
//Add retString to itemTile[i]
}
How do I place each individual retString into each tile using the itemTile[i]?
I'm relatively new to coding and Java, so I have a sneaking suspicion I am over complicating things.
If you want to assign values to the itemTile array inside a method like displayItems2, there are two possibilities: 1) pass a reference to itemTile into displayItems2 or 2) make itemTile a class member.
Example 1 (pass a reference):
private void displayItems2(HBox itemTile) {
// [...]
itemTile[i] = descs.get(i);
}
Example 2 (class member):
class MyClass {
// [...]
HBox itemTile;
// [...]
private void displayItems2() {
// [...]
itemTile[i] = descs.get(i);
}
}

Restart observable based on its emitted values with RxJava

I have an observable which I want to emit Integer values, but if one of the emitted values is negative, I want the observable to emit values again with 1 second delay between emissions until there's no negative values.
I found this answer Repeat/Resubscribe to Observable with condition based on emitted item(s) and I don't really like it because it uses recursion which may slow a device down (depending on how many attempts it'd take to get the proper results).
Is there any other (proper) way of doing that? I also don't know how to set a delay to each emission except for the first one.
Here's what I have now:
getObservable().subscribe(valueList -> {
for (Integer value : valueList) {
Log.d("TAG", "value: " + value);
}
});
private Observable<List<Integer>> getObservable() {
return Observable.fromCallable(() -> {
List<Integer> list = new ArrayList<>();
Random random = new Random();
for (int i = 0; i < 10; i++) {
list.add(random.nextInt(12) - 1);
}
return list;
}).flatMap(valueList -> {
for (int i = 0; i < valueList.size(); i++) {
if (valueList.get(i) < 0) {
Log.d("TAG", "Negative value = " + valueList.get(i) + ", index = " + i);
return getObservable().delay(1, TimeUnit.SECONDS);;
}
}
return Observable.just(valueList);
});
}

JavaFx CheckTreeView how to check which item is unchecked?

I am using ControlsFX for CheckTreeView. I have lots of elements in CheckTreeView and i dont want to traverse through all the elements in this tree ( because it takes lots of time due to number of elements in the tree). Is there a method like checkTreeView.getLastUncheckedItem(); to get the last unchecked one.
Currently I am checking the number of elements that checked and comparing it with counter.
If (CountPrev > Count){
//Something Unchecked Do Stuff
}
But again, i cant find what is unchecked without traverse through all elements.
EDIT:
When user checks an item on CheckTreeView, I get that item by
String lastCheckedItem = checkTreeView.getCheckModel().
getCheckedItems().get(treeView.getCheckModel().getCheckedItems().size()-1).toString();
Now I need something like this for the unchecked item
Take a ArrayList 'allItem' and Store all TreeItems, then
after Store selected item in ObservableList 'Selecteditems' using
getCheckedItems() method, Now remove selected item in ArrayList like
below code:
Here allTreeItems is a CheckBoxTreeItem
List<String> allItem = new ArrayList<>();
for (int j = 0; j < allTreeItems.getValue().length(); j++) {
allItem.add(allTreeItems.getChildren().get(j).getValue());
}
if (CountPrev > Count) {
ObservableList<TreeItem<String>> Selecteditems = checkTreeView.getCheckModel().getCheckedItems();
allItem.remove(Selecteditems);
System.out.println("UnChecked Item :" + allItem);
for (int k = 0; k < allItem.size(); k++) {
System.out.println(allItem.get(k));
}
}
Guys thank you so much for your help!
I've accepted Calips' answer because of time and effort he gave for my question.
This is what I've been looking for:
checkTreeView.getCheckModel().getCheckedItems().addListener(new ListChangeListener<TreeItem<String>>() {
#Override public void onChanged(ListChangeListener.Change<? extends TreeItem<String>> change) {
updateText(checkedItemsLabel, change.getList());
while (change.next()) {
System.out.println("============================================");
System.out.println("Change: " + change);
System.out.println("Added sublist " + change.getAddedSubList());
System.out.println("Removed sublist " + change.getRemoved());
System.out.println("List " + change.getList());
System.out.println("Added " + change.wasAdded() + " Permutated " + change.wasPermutated() + " Removed " + change.wasRemoved() + " Replaced "
+ change.wasReplaced() + " Updated " + change.wasUpdated());
System.out.println("============================================");
}
}
});
Resource:
https://github.com/jinghai/controlsfx/blob/master/controlsfx-samples/src/main/java/org/controlsfx/samples/checked/HelloCheckTreeView.java
Stack<YourClassOfTheCheckModel> recentlyUnchcked = new Stack<YourClassOfTheCheckModel>();
yourTreeView.getSelectionModel().
selectedItemProperty().addListener( new ChangeListener() {
#Override
public void changed(ObservableValue observable, Object oldValue,
Object newValue) {
TreeItem<YourClassOfTheCheckModel> selectedItem =
(TreeItem<YourClassOfTheCheckModel>) newValue;
CheckModel checkModel = checkTreeView.getCheckModel().
bool checked = checkModel.isChecked (selectedItem);
if(checked==false){
recentlyUnchcked.push(yourObjectOfTheCheckModel);
}
}
});
Hope this will help or give you an idea though i don't know if this will work (code not tested, have no IDE right now).

How do I get the correct output for the try/catch statement?

I want to add a new item in the list by inputting the number for the position of the list. When I run this code for the app, even without inputting a number, only the catch statement is executed. How do I get the try statement executed? Here is the code that I typed (Please ignore the lines of the code for manually adding items to the list l1 unless it have to change to fix my problem):
public void m(View view) {
//Define reference for the list
List<Integer> l1;
int x;
int y;
int z; //For storing removed item
EditText input;
TextView tv;
int pos; //For position of the list that user input
input = (EditText) findViewById(R.id.user_input);
tv = (TextView) findViewById(R.id.text_answer);
pos = input.getInputType();
//Create the list
l1 = new ArrayList<Integer>();
//Add items to the list l1
l1.add(0, 20);
l1.add(1, 52);
//Display the size
tv.setText("List's size is " + l1.size() + "\n");
//Retrieve an item
x = l1.get(0);
//Display the retrieved item
tv.append("Retrieved value is " + x + "\n");
//Add more items to the list, but change its position
l1.add(0, 61);
l1.add(1, 17);
l1.add(2, 6);
//Show the updated size
tv.append("After adding more items, List's size is " + l1.size() + "\n");
//Retrieve an item at position (or index) 2
y = l1.get(2);
//Display the new retrieved item
tv.append("The second retrieved item is " + y + "\n");
//Remove an item at position 3
z = l1.get(3);
tv.append("Next, I will remove the item at position 3, which is " + z + "\n");
l1.remove(3);
//Display the final size
tv.append("After removing one item from the list, List's size is " + l1.size() + "\n");
//Use the toast message
try {
l1.add(pos, 777);
Toast.makeText(MainActivity.this, "Added item to the list", Toast.LENGTH_SHORT).show();
} catch(IndexOutOfBoundsException e) {
Toast.makeText(MainActivity.this, "Could not add item to thie list. Bad index:" +
pos, Toast.LENGTH_SHORT).show();
}
}
You read pos as ;
pos = input.getInputType();
This might cause IndexOutOfBoundsException at all times. Instead you might want to convert EditText content into int somewhere around this line of code ;
pos = Integer.parseInt(input.getText().toString());
Plus add some sanity checking to avoid integer parse exceptions.

Locker Program... Displaying the method once a button is clicked

I am doing the 1000 locker program. I am having one problem though, the code functions and with system.out.println it will display how I want it to display but, in the text area it won't display. Please Help Me, and commenting would be a great help. Thanks in Advance!
String output = "";
int numOpen = 0;
String numCount = "";
(Above code is declared at top of program)
private int runLockers(int Lockers)
{
final int numLockers = Integer.valueOf(numLockerTextField.getText());
int numClosed = Integer.valueOf(numLockerTextField.getText());
boolean lockers[] = new boolean[numLockers+1];
for(int studentNum = 1; studentNum <= numLockers; studentNum++)
{
for(int locker = studentNum; locker <= numLockers; locker+=studentNum)
{
lockers[locker]=!lockers[locker];
}
}
for(int count=1; count <= numLockers; count++)
{
if(lockers[count])
{
numOpen++;
numCount+="Locker: "+count+"\n";
System.out.println("Open Lockers:" + numOpen);
System.out.println(numCount);
output+="Open Lockers:" + numOpen + numCount;
}
}
//outputTextArea.setText(output);
return(numOpen);
}
private void simulateBtnActionPerformed (ActionEvent event)
{
outputTextArea.setText(output);
outputTextArea.setText("There are "+ Integer.valueOf(numLockerTextField.getText()) +" lockers, and "+ runLockers(0) +" are left open.");
}
This is the sumulate button code. It is before the method:
simulateButton = new JButton(); //declaring my new JButton
simulateButton.setText("Simulate"); //setting the text of the JButton
simulateButton.setBounds(160,500,100,30); //setting the bounds to which the Button is set to; The int x&y also the width&height
contentPane.add(simulateButton); //adding label to contentPane so it will be visible to user
simulateButton.addActionListener // adding an interface used to listen for an action event
(
new ActionListener()
{
public void actionPerformed( ActionEvent event )
{
simulateBtnActionPerformed(event);
}
} // referencing what action is to be perform when button is pressed
);
Here is an example of how it out prints :
Open Lockers:1
Locker: 1
Open Lockers:2
Locker: 1
Locker: 4
Open Lockers:3
Locker: 1
Locker: 4
Locker: 9
This is the only line that appears in text area:
outputTextArea.setText("There are "+ Integer.valueOf(numLockerTextField.getText()) +" lockers, and "+ runLockers(0) +" are left open.");
... which looks like
There are 1000 lockers, and 31 are left open.
This is what the text area SHOULD look like:
Open Lockers:1
Locker: 1
Open Lockers:2
Locker: 1
Locker: 4
Open Lockers:3
Locker: 1
Locker: 4
Locker: 9
(.... that goes to 1000)
There are 1000 lockers, and 31 are left open.
You're setting the text of outputTextArea to output and then immediately replacing that with other text (the "There are ..." string). You probably want to be appending strings instead of setting the text twice. Maybe something like this:
private void simulateBtnActionPerformed (ActionEvent event)
{
outputTextArea.setText(output
+ "\nThere are "+ Integer.valueOf(numLockerTextField.getText()) +" lockers, and "+ runLockers(0) +" are left open.");
}

Categories