How to implement a constantly active loop to check for changes? - loops

I created an empty TextField test and an empty TextField test2 in the "start" method
public void start(Stage primaryStage) throws Exception {}
Now I want to check constantly if test.getText().equals(""). If so, test2.setEditable(false), otherwise test2.setEditable(true).
I don't know how to implement it, as it needs to get checked constantly.
I already tried to implement an if-Statement in the start method and it actually set test2 on notEditable at the beginning, astest is empty but when test.getText().equals("") changed to !test.getText().equals("") test2 was still not editable.

You can do this by binding the editable property of test2 to the text property of test.
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.TextField;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class Main extends Application {
#Override
public void start(Stage primaryStage) {
TextField test = new TextField();
TextField test2 = new TextField();
// do the binding
test2.editableProperty().bind(test.textProperty().isEmpty().not());
VBox root = new VBox(20, test, test2);
root.setAlignment(Pos.CENTER);
root.setPadding(new Insets(50));
primaryStage.setScene(new Scene(root, 300, 150));
primaryStage.setTitle("Example");
primaryStage.show();
}
}
The text property of TextField is a StringProperty. This class has the method isEmpty (inherited by StringExpression) that returns a BooleanBinding that will hold true if the StringProperty's value is empty or null. The not() call negates the value of the BooleanBinding which means test2 will only be editable if test's text is not empty.

Instead of checking all the time you can just listen on changes like this:
test.textProperty().addListener((observable, oldValue, newValue) -> {
if (newValue.equals("")) {
test2.setEditable(false);
}
);

Related

MapContainer show only on click/touch

I am trying to use naive map.
I have places a MapContainer insider a Form Component but the From shows blank without the map inside it, on the simulator. When I click on the viewport the map shows as long as the mouse button remains down. When I release it disappear again.
Is it a real problem or is it a misfunction of the simulator? If it is a real problem what am I doing wrong?
below is the class I am using:
package com.mainsys.zappeion;
import com.codename1.googlemaps.MapContainer;
import com.codename1.maps.Coord;
import com.codename1.ui.Form;
import com.codename1.ui.layouts.BorderLayout;
/**
*
* #author Christoforos
*/
public class ZappeionMap extends com.codename1.ui.Form {
private Form current;
public ZappeionMap() {
super("Ζάππειον", new BorderLayout());
}
#Override
public void show() {
if(current != null){
current.show();
return;
}
final MapContainer cnt = new MapContainer();
this.addComponent(BorderLayout.CENTER, cnt);
cnt.setCameraPosition(new Coord(41.889, -87.622));
super.show();
}
}
/********** Implementing Shai's answer ******************/
I changed my code to what Shai suggested show my class now is:
package com.mainsys.zappeion;
import com.codename1.googlemaps.MapContainer;
import com.codename1.location.Location;
import com.codename1.location.LocationManager;
import com.codename1.maps.Coord;
import com.codename1.ui.BrowserComponent;
import com.codename1.ui.FontImage;
import com.codename1.ui.Form;
import com.codename1.ui.layouts.BorderLayout;
import com.codename1.ui.plaf.Style;
/**
*
* #author Christoforos
*/
public class ZappeionMap extends com.codename1.ui.Form {
private Form current;
private static final String HTML_API_KEY = "AIzaSyDHlFJK561bQVs0AyBm1M5xWS_YCHNuPfc";
public ZappeionMap() {
super("Ζάππειον", new BorderLayout());
final MapContainer cnt = new MapContainer( HTML_API_KEY );
this.addComponent(BorderLayout.CENTER, cnt);
cnt.setCameraPosition(new Coord(41.889, -87.622));
}
}
It still having the same problem. The screen is blank. The map only shown when I click on the screen.
I also noticed something else. On the debuger I get the message:
WARNING: Apple will no longer accept http URL connections from applications you tried to connect to http://tile.openstreetmap.org/4/2/9.png to learn more check out https://www.codenameone.com/blog/ios-http-urls.html
Why is it trying to connect to http://tile.openstreetmao.org. It is supposed to work with google maps not with openstreet maps.
One more information, maybe it is worh something. I test it on real device. The screen is still blink but when I touch the screen it does not show anythink, in contrast with the simulater that when I click on the screen the map appears.
I am using netbeans 8.2 on centos 7
Any help is appreciated.
Thank you Christoforos.
Why are you overriding the show method of form and don't construct the UI n the constructor?
It looks like you copied some code from the lifecycle class and mixed it with a form subclass e.g. the current variable.
This is closer to correct:
public class ZappeionMap extends com.codename1.ui.Form {
private Form current;
public ZappeionMap() {
super("Ζάππειον", new BorderLayout());
final MapContainer cnt = new MapContainer();
this.addComponent(BorderLayout.CENTER, cnt);
cnt.setCameraPosition(new Coord(41.889, -87.622));
}
}

TreeView one-at-a-time hander on CheckBoxTreeItem changes

I'm beginner in JavaFX.
I need to make one-at-a-time handler for any changes in the check boxes for my TreeView. Now it works like it handles all selected nodes simultaneously.
Thanks for help. Here is my code:
package sample;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.CheckBoxTreeItem;
import javafx.scene.control.TreeView;
import javafx.scene.control.cell.CheckBoxTreeCell;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
public class Main extends Application {
#Override
public void start(Stage primaryStage) throws Exception{
BorderPane root = new BorderPane();
root.setCenter(initTreeView());
primaryStage.setTitle("Hello World");
primaryStage.setScene(new Scene(root, 300, 275));
primaryStage.show();
}
public TreeView initTreeView() {
TreeView<String> treeView = new TreeView<>();
treeView.setRoot(new CheckBoxTreeItem<>("123"));
treeView.getRoot().addEventHandler(CheckBoxTreeItem.checkBoxSelectionChangedEvent(), event -> System.out.println("hello"));
treeView.setCellFactory(p -> new CheckBoxTreeCell<>());
treeView.getRoot().getChildren().addAll(new CheckBoxTreeItem<>("1"),new CheckBoxTreeItem<>("2"), new CheckBoxTreeItem<>("3"));
treeView.getRoot().getChildren().get(0).getChildren().addAll(new CheckBoxTreeItem<>("4"),new CheckBoxTreeItem<>("5"), new CheckBoxTreeItem<>("6"));
treeView.getRoot().getChildren().get(1).getChildren().addAll(new CheckBoxTreeItem<>("7"),new CheckBoxTreeItem<>("8"), new CheckBoxTreeItem<>("9"));
treeView.getRoot().getChildren().get(2).getChildren().addAll(new CheckBoxTreeItem<>("10"),new CheckBoxTreeItem<>("11"), new CheckBoxTreeItem<>("12"));
return treeView;
}
public static void main(String[] args) {
launch(args);
}
}
Actually it works correctly. Your event handler is called once for every changed checkbox node. Just note that changing subnodes affects parent ones as well, so you get several event handles calls.
Try next code instead which prints the name of the affected checkbox:
treeView.getRoot().addEventHandler(CheckBoxTreeItem.checkBoxSelectionChangedEvent(),
event -> System.out.println("hello " + event.getTreeItem().getValue()));
For example, if you click on checkbox "5" you will get the following log:
hello 5
hello 1
hello 123
because all parent node have changed state as well (from unchecked to intermediate "-" state). If you click "6" after that only one checkbox is affected and output will be:
hello 6

How to temporarily remove items from a ChoiceBox (or maybe a ComboBox)?

I've come across a somewhat perplexing conundrum. I've recently started to figure out how to work with listeners, thanks to some people on here, and I'm trying to find a way to use them in conjunction with choice/comboboxes to do something tricky. What I want to have happen is, when the user makes a selection from one of six linked boxes containing six choices, it removes that option from the other 5 boxes until either A: the option is changed to one of the remaining ones, or B: the option is changed to a null or default setting (to prevent getting "locked in" after picking, or maybe I can just make a reset button for that purpose). I've got a ChangeListener on each choicebox now, but various things I've tried (switch statements, assigning each answer a boolean, various attempts to use .getItems().remove() in vain, I've been at this a while) Has anyone figured or seen an example of how this could be done? Thanks in advance for any advice, you guys(and gals) have helped me learn by leaps and bounds these past few weeks.
if you want something like this:
I had this code in my program. it is nor really efficient, but was fine for me on a small set of data.
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.control.ChoiceBox;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
public class ConnectedComboBox<T> implements ChangeListener<T> {
private ObservableList<T> items;
private List<ChoiceBox<T>> comboBoxList = new ArrayList<>();
public ConnectedComboBox(ObservableList<T> items){
this.items = items;
if (this.items == null) this.items = FXCollections.observableArrayList();
}
public void addComboBox(ChoiceBox<T> comboBox){
comboBoxList.add(comboBox);
comboBox.valueProperty().addListener(this);
updateSelection();
}
public void removeComboBox(ChoiceBox<T> comboBox){
comboBoxList.remove(comboBox);
comboBox.valueProperty().removeListener(this);
updateSelection();
}
// this boolean needed because we can set combobox Value in updateSelection()
// this will trigger a value listener and update selection one more time => stack overflow
// this behavior occurs only if we have more than one equal item in source ObservableList<T> items list.
private boolean updating = false;
private void updateSelection() {
if (updating) return;
updating = true;
List<T> availableChoices = items.stream().collect(Collectors.toList());
for (ChoiceBox<T> comboBox: comboBoxList){
if (comboBox.getValue()!= null) {
availableChoices.remove(comboBox.getValue());
}
}
for (ChoiceBox<T> comboBox: comboBoxList){
T selectedValue = comboBox.getValue();
ObservableList<T> items = comboBox.getItems();
items.setAll(availableChoices);
if (selectedValue != null) {
items.add(selectedValue);
comboBox.setValue(selectedValue);
}
}
updating = false;
}
#Override
public void changed(ObservableValue<? extends T> observable, T oldValue, T newValue) {
updateSelection();
}
}
And here is how you use it:
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.ChoiceBox;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
public class MainFX extends Application {
#Override
public void start(Stage primaryStage) throws Exception {
HBox root = new HBox();
root.setSpacing(10);
ObservableList<String> values = FXCollections.observableArrayList("One", "Two", "Three", "Four","Five");
ChoiceBox<String> combo1 = new ChoiceBox<>();
combo1.setPrefWidth(100);
ChoiceBox<String> combo2 = new ChoiceBox<>();
combo2.setPrefWidth(100);
ChoiceBox<String> combo3 = new ChoiceBox<>();
combo3.setPrefWidth(100);
root.getChildren().addAll(combo1,combo2,combo3);
ConnectedComboBox<String> connectedComboBox = new ConnectedComboBox<>(values);
connectedComboBox.addComboBox(combo1);
connectedComboBox.addComboBox(combo2);
connectedComboBox.addComboBox(combo3);
primaryStage.setScene(new Scene(root,600,600));
primaryStage.show();
}
public static void main(String[] args){
launch(args);
}
}

Different events for CheckBox's box and label?(JavaFX)

I want my CheckBox to become selected only when box is clicked. If CheckBox's label is clicked I want to perform different action with this CheckBox being not selected. How is it possible to achieve this?
I made separate checkbox and label. But I can't change label's pseudo class through checkbox. They are al in listview. Here is a part of the code:
HBox todoHBox=new HBox(0);
CheckBox todoCheckBox=new CheckBox();
Label todoLabel=new Label(item.getName());
Label timeLabel=new Label();
Region rSpring = new Region();
todoHBox.setPrefWidth(300);
todoHBox.setHgrow(rSpring, Priority.ALWAYS);
todoHBox.setHgrow(timeLabel, Priority.ALWAYS);
todoHBox.setHgrow(todoCheckBox, Priority.NEVER);
timeLabel.setMinWidth(60);
timeLabel.getStyleClass().add("time-label");
todoLabel.getStyleClass().add("todo-label");
todoHBox.getChildren().addAll(todoCheckBox,todoLabel,rSpring,timeLabel);
todoHBox.setMargin(timeLabel, new Insets(3,0,0,0));
PseudoClass pseudo = PseudoClass.getPseudoClass("task-done");
todoCheckBox.selectedProperty().addListener(e->{
if(todoCheckBox.isSelected()){
todoLabel.pseudoClassStateChanged(pseudo, true);
}else{
todoLabel.pseudoClassStateChanged(pseudo, false);
}});
setGraphic(todoHBox);
Just use two controls: a CheckBox with no text and a Label. Call setOnMouseClicked(...) on the Label with a handler that does whatever you need.
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.CheckBox;
import javafx.scene.control.Label;
import javafx.scene.layout.HBox;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class CheckBoxWithLabelExample extends Application {
#Override
public void start(Stage primaryStage) {
CheckBox checkBox = new CheckBox();
checkBox.selectedProperty().addListener((obs, wasSelected, isNowSelected) ->
System.out.println("Check box is now "+(wasSelected ? "not ":"") + "selected"));
Label label = new Label("Make Task");
label.setOnMouseClicked(e -> System.out.println("Text clicked"));
HBox control = new HBox(checkBox, label);
Scene scene = new Scene(new StackPane(control), 350, 75);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}

where is the underscore in my CheckBox?

The shortest possible program to show my problem:
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.CheckBox;
import javafx.scene.control.Label;
import javafx.scene.layout.Priority;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class TestCheckBox extends Application {
public static void main(String[] args) {
launch(args);
}
public void start(Stage stage) {
Scene scene = new Scene(new StackPane());
final VBox vbox = new VBox();
vbox.getChildren().addAll(new Label("ABC_DEF"), new CheckBox("ABC_DEF"));
((StackPane) scene.getRoot()).getChildren().add(vbox);
stage.setScene(scene);
stage.show();
}
}
leads to:
In SceneBuilder by comparison it´s displayed normally, but not in my application. I am running Java 1.8.0-b129
Any hint?
You probably want to setMnemonicParsing to false on the CheckBox.
MnemonicParsing property to enable/disable text parsing. If this is set to true, then the Label text will be parsed to see if it contains the mnemonic parsing character '_'. When a mnemonic is detected the key combination will be determined based on the succeeding character, and the mnemonic added.
The default value for Labeled is false, but it is enabled by default on some Controls.

Resources