How to access values from automatically generated Labels? - java

Here I receive an ObservableList of Products. Then for each Product in the List I create a Label for the name, price and quantity. I also create two Buttons, to add and remove quantity, altering the value in the label. My problem is in the ´escolherProdutos()´ method, where I want to access the value of each Label respective to de quantity so I can know what quantities of each product are being requested, and I cant seem to access these values from outside the populateFlowPane() method. This is probably not the best solution to my problem, and I am a beginner, so if you can help me solve my problem or even have a better way of doing this I would be really grateful.
public class EscolherProdutosController
{
#FXML private VBox nomesVBox;
#FXML private VBox precoVBox;
#FXML private VBox qtdsVBox;
#FXML private Button escolherBtn;
private static ArrayList<Label> quantidades = new ArrayList<>();
#FXML
public void initialize()
{
populateFlowPane();
}
public void populateFlowPane()
{
ObservableList<Produto> produtos = Logic.getProdutos();
produtos.forEach(prod -> {
HBox hbox = new HBox(5);
Label nome = new Label(prod.getNome());
Label preco = new Label(String.valueOf(prod.getPreco()));
Button minus = new Button("-");
minus.setMinSize(20, 20);
Label qtd = new Label("0");
Button plus = new Button("+");
nomesVBox.getChildren().add(nome);
precoVBox.getChildren().add(preco);
hbox.getChildren().addAll(minus, qtd, plus);
qtdsVBox.getChildren().add(hbox);
//remover unidades do produto
minus.setOnAction((ActionEvent e) -> {
int quantidade = Integer.parseInt(qtd.getText());
if(quantidade >= 1)
{
quantidade--;
qtd.setText(String.valueOf(quantidade));
}
});
//adicionar unidades do produto
plus.setOnAction((ActionEvent e) -> {
int quantidade = Integer.parseInt(qtd.getText());
if(quantidade >= 0)
{
quantidade++;
qtd.setText(String.valueOf(quantidade));
}
});
quantidades.add(qtd);
});
}
public void escolherProdutos()
{
ObservableList<Produto> produtos = Logic.getProdutos();
produtos.forEach(prod -> {
quantidades.forEach(qtd -> {
Logic.escolherProdutos(prod.getIdProduto(),
Integer.parseInt(qtd.getText()));
});
});
}
}

I would probably add them to a list and access them accordingly im not sure what you need from them because you are being vague but take a look at the code sample below
public class MySceneController {
#FXML private ListView listView;
private ArrayList<Label> labelList = new ArrayList<>();
#FXML
public void initialize()
{
populateListView();
}
public void populateListView()
{
ObservableList<Products> products = Logic.getProducts();
products.forEach(prod -> {
Label label = new Label(prod.getName());
//Add them to a list here
labelList.add(label);
listView.getItems().addAll(results);
});
}
public void doSomething()
{
for (Label label : labelList) {//Maybe iterate through the list depending on what you need
//do something
}
//Here is where I need to access the label values
}
}

I solved the problem. Maybe it's not the best solution, but it works for me. What I did was create a HashMap where the product ID is the key and the quantity is the value.
Then for the add and remove buttons, I simply replace the value for the corresponding key in the HashMap. Doing this, I can then use it as input for the escolherProdutos() method from the Logic class, to select the products.
public class EscolherProdutosController
{
#FXML private VBox nomesVBox;
#FXML private VBox precoVBox;
#FXML private VBox qtdsVBox;
private HashMap<BigDecimal, Integer> quantidades = new HashMap<>();
#FXML
public void initialize()
{
populateFlowPane();
}
public void populateFlowPane()
{
ObservableList<Produto> produtos = Logic.getProdutos();
produtos.forEach(prod -> {
HBox hbox = new HBox(5);
Label nome = new Label(prod.getNome());
Label preco = new Label(String.valueOf(prod.getPreco()));
Button minus = new Button("-");
minus.setMinSize(20, 20);
Label qtd = new Label("0");
Button plus = new Button("+");
nomesVBox.getChildren().add(nome);
precoVBox.getChildren().add(preco);
hbox.getChildren().addAll(minus, qtd, plus);
qtdsVBox.getChildren().add(hbox);
//remover unidades do produto
minus.setOnAction((ActionEvent e) -> {
Integer quantidade = Integer.parseInt(qtd.getText());
if(quantidade >= 1)
{
quantidade--;
qtd.setText(String.valueOf(quantidade));
if(quantidades.containsKey(prod.getIdProduto()))
quantidades.replace(prod.getIdProduto(), quantidade);
else
quantidades.put(prod.getIdProduto(), quantidade);
}
});
//adicionar unidades do produto
plus.setOnAction((ActionEvent e) -> {
Integer quantidade = Integer.parseInt(qtd.getText());
if(quantidade >= 0)
{
quantidade++;
qtd.setText(String.valueOf(quantidade));
if(quantidades.containsKey(prod.getIdProduto()))
quantidades.replace(prod.getIdProduto(), quantidade);
else
quantidades.put(prod.getIdProduto(), quantidade);
}
});
});
}
public void escolherProdutos()
{
Logic.escolherProdutos(quantidades);
}

Related

JavaFX call method in Button with the correst String from List

i am new here, am new in programming and i am trying to create a Java app with Selenium and JavaFX. In this app i should be able to check the links of a page and also could be able to show the pointed link. For the moment the programm can check all the links on a page but it can't show the correct link. I display all urls in a ListView with a button and in this buttons calls the method to show the link but for every button in the list it always shows the same url/link because it is the last value taken from the variable url in a while loop. And also i have 4 tabs where i track the HTTP Status of each link. For all 200 HTTP status they are inserted in the "200s" tab, for the 300 in the "300s" tab, the same for the 400 and 500. I have a variable respCode for the HTTP status but it always displays the last value in the while loop (200). Here is a code snippet to have a look on it:
public class AutoTestController
{
// location and resources will be automatically injected by the FXML loader
#FXML
private Button buttonSearch;
#FXML
private Button buttonCheck;
#FXML
private Button buttonAllLinks;
#FXML
private ChoiceBox switchLogin;
#FXML
private TextField testUrl;
#FXML
private TextField stageUrl;
#FXML
private TextField stageIntUrl;
#FXML
private TextField testUrlLiveInt;
#FXML
private TextField testUrlStage;
#FXML
private TextField testUrlStageInt;
#FXML
private TextField customerIdLogin;
#FXML
private TextField customerIdLoginLiveInt;
#FXML
private TextField oneCustomerIdLoginLiveInt;
#FXML
private TextField customerIdLoginStage;
#FXML
private TextField customerIdLoginStageInt;
#FXML
private TextField oneCustomerIdLoginStageInt;
#FXML
private PasswordField passwordLogin;
#FXML
private PasswordField passwordLoginStage;
#FXML
private PasswordField onePasswordLoginLiveInt;
#FXML
private PasswordField onePasswordLoginStageInt;
#FXML
private TextField linkText;
#FXML
private TextField linkTextTwo;
#FXML
private TextField linkTextThree;
#FXML
private TextField linkTextFour;
#FXML
private TextField linkTextFive;
#FXML
private TextField linkTextEmpty;
#FXML
private TextField linkTextAnother;
#FXML
private int textLinks;
#FXML
private ChoiceBox countrySelector;
#FXML
private ChoiceBox countrySelectorLiveInt;
#FXML
private StackPane paneTwo;
#FXML
private StackPane paneThree;
#FXML
private StackPane paneFour;
#FXML
private StackPane paneFive;
private static WebDriver driver = null;
#FXML
private int respCode = 200;
#FXML
private static int linkCount=0;
#FXML
private static int linkCountTwo=0;
#FXML
private static int linkCountThree=0;
#FXML
private static int linkCountFour=0;
#FXML
private static int linkCountFive=0;
#FXML
private static int linkCountEmpty=0;
#FXML
private static int linkCountAnother=0;
#FXML
private String url = "";
private int counter=0;
private ObservableList<String> listTwo;
private ObservableList<String> listThree;
private ObservableList<String> listFour;
private ObservableList<String> listFive;
private List<String> urlsTwo = new ArrayList<>();
private List list = new ArrayList<>();
private List<String[]> urlsTwo2 = new ArrayList<>();
private List<String> urlsThree = new ArrayList<>();
private List<String> urlsFour = new ArrayList<>();
private List<String> urlsFive = new ArrayList<>();
// Add a public no-args constructor
public AutoTestController()
{
}
public class XCell extends ListCell<String> {
HBox hB = new HBox();
Label label = new Label("Empty");
Pane pane = new Pane();
Button bB = new Button("Show Link");
String lastItem = "";
public XCell() {
super();
hB.getChildren().addAll(bB, new Text(" (" + respCode + ") : "), label, pane, new Text(" "));
HBox.setHgrow(paneTwo, Priority.ALWAYS);
bB.setUserData(url);
bB.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent eventTwo) {
Button thisButton = (Button) eventTwo.getSource();
WebElement linkTwo = driver.findElement(By.xpath("//a[contains(#href, '" + thisButton.getUserData() + "')]"));
scrolltoElement(linkTwo);
HighlightThisLink(driver, linkTwo);
}
});
}
#Override
protected void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
setText(null); // No text in label of super class
if (empty) {
lastItem = null;
setGraphic(null);
} else {
lastItem = item;
label.setText(item!=null ? item : "<null>");
setGraphic(hB);
}
}
}
#FXML
private void initialize()
{
countrySelector.getItems().addAll("DE","US","CA","UK","FR","ES","IT","MX");
countrySelector.getSelectionModel().selectFirst();
countrySelectorLiveInt.getItems().addAll("DE","US","CA","UK","FR","ES","IT","MX");
countrySelectorLiveInt.getSelectionModel().selectFirst();
}
#FXML
private void CheckLink(){
String theUrl = "";
System.setProperty("webdriver.chrome.driver", "chromedriver.exe");
HttpURLConnection huc = null;
driver.navigate();
List<WebElement> links = driver.findElements(By.tagName("a"));
linkCount = links.size();
System.out.println("Total Links on Page : "+linkCount);
linkText.setText("Total Links on Page : " + linkCount);
Iterator<WebElement> it = links.iterator();
while(it.hasNext()){
url = it.next().getAttribute("href");
if(url == null || url.isEmpty()){
System.out.println("URL is either not configured for anchor tag or it is empty");
linkCountEmpty++;
System.out.println("Number of empty urls : " + linkCountEmpty);
linkTextEmpty.setText("Number of empty urls : " + linkCountEmpty);
continue;
}
if(!url.startsWith(theUrl)){
System.out.println("URL " + url + " belongs to another domain, skipping it.");
linkCountAnother++;
System.out.println("Number of another domain : " + linkCountAnother);
linkTextAnother.setText("Number of other : " + linkCountAnother);
continue;
}
try {
huc = (HttpURLConnection)(new URL(url).openConnection());
huc.setRequestMethod("HEAD");
huc.connect();
respCode = huc.getResponseCode();
if(respCode >= 200 && respCode <= 226) {
urlsTwo.add(url);
listTwo = FXCollections.observableArrayList(urlsTwo);
ListView<String> lvTwo = new ListView<>(listTwo);
lvTwo.setCellFactory(new Callback<ListView<String>, ListCell<String>>() {
#Override
public ListCell<String> call(ListView<String> param) {
return new XCell();
}
});
paneTwo.getChildren().add(lvTwo);
System.out.println(respCode+": "+url+" is a success link");
linkCountTwo++;
System.out.println("Number of 200s : " + linkCountTwo);
linkTextTwo.setText("Number of 200s : " + linkCountTwo);
}
if(respCode >= 300 && respCode <= 308) {
urlsThree.add(url);
listThree = FXCollections.observableArrayList(urlsThree);
ListView<String> lvThree = new ListView<>(listThree);
lvThree.setUserData(respCode);
lvThree.setCellFactory(new Callback<ListView<String>, ListCell<String>>() {
#Override
public ListCell<String> call(ListView<String> param) {
return new XCell();
}
});
paneThree.getChildren().add(lvThree);
System.out.println(respCode+": "+url+" is a redirection link");
linkCountThree++;
System.out.println("Number of 300s : " + linkCountThree);
linkTextThree.setText("Number of 300s : " + linkCountThree);
}
if(respCode >= 400 && respCode <= 499) {
urlsFour.add(url);
listFour = FXCollections.observableArrayList(urlsFour);
ListView<String> lvFour = new ListView<>(listFour);
lvFour.setUserData(respCode);
lvFour.setCellFactory(new Callback<ListView<String>, ListCell<String>>() {
#Override
public ListCell<String> call(ListView<String> param) {
return new XCell();
}
});
paneFour.getChildren().add(lvFour);
System.out.println(respCode+": "+url+" is a client error link");
linkCountFour++;
System.out.println("Number of 400s : " + linkCountFour);
linkTextFour.setText("Number of 400s : " + linkCountFour);
}
if(respCode >= 500 && respCode <= 599) {
urlsFive.add(url);
listFive = FXCollections.observableArrayList(urlsFive);
ListView<String> lvFive = new ListView<>(listFive);
lvFive.setUserData(respCode);
lvFive.setCellFactory(new Callback<ListView<String>, ListCell<String>>() {
#Override
public ListCell<String> call(ListView<String> param) {
return new XCell();
}
});
paneFive.getChildren().add(lvFive);
System.out.println(respCode+": "+url+" is a server error link");
linkCountFive++;
System.out.println("Number of 200s : " + linkCountFive);
linkTextFive.setText("Number of 200s : " + linkCountFive);
}
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public static void scrolltoElement(WebElement ScrolltoThisElement) {
Coordinates coordinate = ((Locatable) ScrolltoThisElement).getCoordinates();
coordinate.onPage();
coordinate.inViewPort();
}
#FXML
private void HighlightThisLink(WebDriver driver, WebElement element) {
driver.navigate();
JavascriptExecutor js = (JavascriptExecutor) driver;
js.executeScript("arguments[0].setAttribute('style', 'background: yellow; border: 2px solid red;');", element);
try {
Thread.sleep(5000);
}
catch (InterruptedException e) {
System.out.println(e.getMessage());
}
js.executeScript("arguments[0].setAttribute('style','border: solid 2px white')", element);
}
}
Here is a capture of the programm with JavaFX:
Link Checker Programm 200s
Link Checker Programm 300s
Could someone please help with these issues?
You don't seem to understand the way ListView works:
A ListView creates the cells that are required to display the items when they are needed. You don't control yourself when this is done. You should be able to deal with cell creation happening at any time. There is no 1:1 relation between cells and items. Items may be reassigned to different cells and there may not be a cell for every item.
For this reason retrieving info in cellFactory (which is what you do in your cell constructor) will not work.
You should change the item type allowing you to access all neccessary info and use the ListCell.item property in the Button handler of the cell:
private static class Response {
private final int responseCode;
private final String url;
Response(int responseCode, String url) {
this.responseCode = responseCode;
this.url = url;
}
// getters...
}
private static class XCell extends ListCell<Response> {
private final HBox hB = new HBox();
private final Label label = new Label("Empty");
private final Button bB = new Button("Show Link");
private final Text response = new Text();
public XCell() {
hB.getChildren().addAll(bB, response, label);
bB.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent eventTwo) {
// handle button click using info from cell item
Response item = getItem();
WebElement linkTwo = driver.findElement(By.xpath("//a[contains(#href, '" + item.getUrl() + "')]"));
scrolltoElement(linkTwo);
HighlightThisLink(driver, linkTwo);
}
});
}
#Override
protected void updateItem(Response item, boolean empty) {
super.updateItem(item, empty);
// update display
if (empty || item == null) {
setGraphic(null);
} else {
label.setText(item.getUrl());
response.setText("("+Integer.toString(item.getResponseCode()) + "):");
setGraphic(hB);
}
}
}
#FXML
private void initialize() {
listTwo = FXCollections.observableArrayList();
ListView<Response> lvTwo = new ListView<>(listTwo);
lvTwo.setCellFactory(lv -> new XCell());
paneTwo.getChildren().add(lvTwo);
listThree = FXCollections.observableArrayList();
ListView<Response> lvThree = new ListView<>(listThree);
lvThree.setCellFactory(l -> new XCell());
paneThree.getChildren().add(lvThree);
listFour = FXCollections.observableArrayList();
ListView<Response> lvFour = new ListView<>(listFour);
lvFour.setCellFactory(l -> new XCell());
paneFour.getChildren().add(lvFour);
listFive = FXCollections.observableArrayList();
ListView<Response> lvFive = new ListView<>(listFive);
lvFive.setCellFactory(l -> new XCell());
paneFive.getChildren().add(lvFive);
...
}
try {
huc = (HttpURLConnection)(new URL(url).openConnection());
huc.setRequestMethod("HEAD");
huc.connect();
respCode = huc.getResponseCode();
switch (respCode / 100) {
case 2:
if (respCode <= 226) {
listTwo.add(new Response(respCode, url));
System.out.println(respCode+": "+url+" is a success link");
linkCountTwo++;
System.out.println("Number of 200s : " + linkCountTwo);
linkTextTwo.setText("Number of 200s : " + linkCountTwo);
}
break;
case 3:
if (respCode <= 308) {
listThree.add(new Response(respCode, url));
...
}
break;
case 4:
listFour.add(new Response(respCode, url));
...
break;
case 5:
listFive.add(new Response(respCode, url));
...
break;
}

Introspection (JavaFx)

after having made quite a lot of searches, I leave it up to you.
Here is in my application JavaFx, I use the introspection to generate a gridPane automatically (that I insert then into Dialog). Thus I have TableView, when the user doubles click above, it generates Dialog containing the columns of this TableView.
In this Dialog, thus there is TextFields which allow to modify the values of fields in TableView.
But well, I cannot get back the value of my attributes by means of the introspection, and how make get back the value of the textFields which were created thanks to the introspection?
There is my introspection method :
public static GridPane analyserChamp(Etudiant etu) {
List<String> list = new ArrayList<>();
Class<? extends Etudiant> classPixel = etu.getClass();
Field attribut[] = classPixel.getDeclaredFields();
GridPane gp = new GridPane();
int i=0;
for(Field p : attribut) {
list.add(p.getName());
Label lab = new Label();
if(!p.getName().equals("classe")) {
TextField l = new TextField();
lab.setText(p.getName());
gp.add(l, 1, i);
}else {
ComboBox<String> cb = new ComboBox<String>();
cb.getItems().addAll("1Bi","2Bi","3Bi");
gp.add(cb, 1, i);
}
gp.add(lab, 0, i);
i++;
}
return gp;
}
Here is the code where I call on to the method of introspection :
if(e.getClickCount() == 2) {
Dialog<Etudiant> dialog = new Dialog<>();
Etudiant test = tableViewEtudiant.getSelectionModel().getSelectedItems().get(0);
if(test!=null) {
dialog.setTitle("Editor");
dialog.setHeaderText("You can update your question");
dialog.getDialogPane().setContent(Analysateur.analyserChamp(test));
ButtonType buttonCancel = new ButtonType("Cancel", ButtonData.CANCEL_CLOSE);
ButtonType buttonOk = new ButtonType("Ok", ButtonData.OK_DONE);
dialog.getDialogPane().getButtonTypes().addAll(buttonOk,buttonCancel);
//Confirmation of the edition
Optional<Etudiant> result = dialog.showAndWait();
//Edition of the question in the gson file
GridPane tmp = Analysateur.analyserChamp(test);
if(result.isPresent()) {
// Here ?????
}
}
Thank in advance ;)
There are many ways of solving this, for example, you can use the userData property to store the key of the attributes, so you can iterate later over the GridPane children and obtain each value in the Dialog result converter.
When you introspect the class Etudiant:
if(!p.getName().equals("classe")) {
TextField l = new TextField();
l.setUserData(p.getName()); //Store the attribute name in the TextField
lab.setText(p.getName());
gp.add(l, 1, i);
}else {
ComboBox<String> cb = new ComboBox<String>();
cb.setUserData(p.getName()); //Store the attribute name in the ComboBox
cb.getItems().addAll("1Bi","2Bi","3Bi");
gp.add(cb, 1, i);
}
When you creat the Dialog:
Dialog<Etudiant> dialog = new Dialog<>();
...
GridPane content = Analysateur.analyserChamp(test); //Keep the content accesible
...
dialog.getDialogPane().setContent(content);
...
dialog.setResultConverter(button -> { //Convert the result
Etudiant result = new Etudiant();
for (Node child : content.getChildren()) { //Iterate over the GridPane children
if (child instanceof TextField) {
String attribute = ((TextField)child).getUserData();
String value = ((TextField)child).getTest();
//Set the value in the result attribute via instrospection
}
if (child instanceof ComboBox) {
//Do the same with combos
}
}
});
Store a Supplier for getting the value of the input for a field in a Map<Field, Supplier<?>>. This way you could go through the entries of the map and retrieve the values for the assignments:
public class ReflectionDialog<T> extends Dialog<T> {
public ReflectionDialog(Class<T> type, Supplier<T> factory) throws IllegalAccessException {
GridPane gp = new GridPane();
Field[] fields = type.getDeclaredFields();
// stores getters for result value
final Map<Field, Supplier<?>> results = new HashMap<>();
int i = 0;
for (Field field : fields) {
if (String.class.equals(field.getType())) {
String name = field.getName();
Node input;
Supplier<?> getter;
if ("classe".equals(name)) {
ComboBox<String> cb = new ComboBox<>();
cb.getItems().addAll("1Bi", "2Bi", "3Bi");
getter = cb::getValue;
input = cb;
} else {
TextField l = new TextField();
getter = l::getText;
input = l;
}
results.put(field, getter);
gp.addRow(i, new Label(name), input);
i++;
}
}
getDialogPane().setContent(gp);
getDialogPane().getButtonTypes().addAll(ButtonType.OK, ButtonType.CANCEL);
setResultConverter(buttonType -> {
if (buttonType == ButtonType.OK) {
// create & initialize new object
final T object = factory.get();
results.forEach((k, v) -> {
try {
k.set(object, v.get());
} catch (IllegalAccessException ex) {
throw new IllegalStateException(ex);
}
});
return object;
} else {
return null;
}
});
}
}
public class A {
String classe;
String value;
#Override
public String toString() {
return "A{" + "classe=" + classe + ", value=" + value + '}';
}
}
ReflectionDialog<A> dialog = new ReflectionDialog<>(A.class, A::new);
A result = dialog.showAndWait().orElse(null);
System.out.println(result);

JavaFX: Initialize RadioButton selection status

I need to save the selection status of multiple RadioButtons, so I can see which RadioButton is selected, when I go back to the scene later on. It's not about the userData, it's about to see whether it's selected. Right now I know how to make it work but with a lot of messy copy & paste. Something like this for every ToggleGroup:
#FXML private RadioButton rb1;
#FXML private RadioButton rb2;
public static int[] status = new int[600];
// to save it
if (rb1.getSelect(true)){
status[0] = 1;
} else {
status[0] = 0;
}
// to load it
if (status[0] == 1){
rb1.setSelected(true);
} else {
rb2.setSelected(true);
}
The problem is that I program a survey with more than 300 questions with binary answers. So I have more than 600 different RadioButtons. It'd take hours to implement it this way.
Is there any smart way to do it? I'm grateful for any advice. Thanks in advance!
Here is a SCVExample, that contains the simplest implementation based on my comment: It defines a model (Survey and Question) then binds the GUI to this model.
public class Radios extends Application {
class Survey {
private ObservableList<Question> questions = FXCollections.observableArrayList();
public ObservableList<Question> getQuestions() {
return questions;
}
}
class Question {
private StringProperty text = new SimpleStringProperty("");
private BooleanProperty answer = new SimpleBooleanProperty(false);
public Question(String text) {
setText(text);
}
public boolean isAnswer() {
return answer.get();
}
public BooleanProperty answerProperty() {
return answer;
}
public void setAnswer(boolean answer) {
this.answer.set(answer);
}
public String getText() {
return text.get();
}
public StringProperty textProperty() {
return text;
}
public void setText(String text) {
this.text.set(text);
}
}
#Override
public void start(Stage primaryStage) throws Exception {
// Model
Survey survey = new Survey();
for (int i = 0; i<300; i++) {
Question question = new Question("Do you like number " + i + "?");
question.answerProperty().addListener((obs, oldval,newval) -> {
System.out.println("Question: " + question.getText() + " answer changed from " + oldval + " to " + newval);
});
survey.getQuestions().add(question);
}
// View
VBox root = new VBox();
root.setSpacing(10);
for (Question question : survey.getQuestions()) {
VBox vBox = new VBox();
vBox.setSpacing(5);
HBox answerHBox = new HBox();
answerHBox.setSpacing(20);
vBox.getChildren().addAll(new Label(question.getText()), answerHBox);
RadioButton yes = new RadioButton("Yes");
RadioButton no = new RadioButton("No");
ToggleGroup toggleGroup = new ToggleGroup();
yes.setToggleGroup(toggleGroup);
no.setToggleGroup(toggleGroup);
answerHBox.getChildren().addAll(yes, no);
yes.setSelected(question.isAnswer());
no.setSelected(!question.isAnswer());
toggleGroup.selectedToggleProperty().addListener((observable, oldValue, newValue) -> {
question.setAnswer(newValue.equals(yes));
});
root.getChildren().add(vBox);
}
Scene scene = new Scene(new ScrollPane(root), 500, 500);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
This will generate a survey like:
Console output:
Question: Do you like number 1? answer changed from false to true
Question: Do you like number 3? answer changed from false to true
Question: Do you like number 6? answer changed from false to true
Question: Do you like number 8? answer changed from false to true
Question: Do you like number 8? answer changed from true to false
Question: Do you like number 8? answer changed from false to true

JavaFX custom component get action from button in custom component

I want to get the event of two buttons in my custom component.
the component is a imageview with two buttons to move between images, but I need to get the position of the image that is currently displayed, Im storing the key of the image, but I need to know when a button have been pressed outside the custom component, so I can change a Label outside the custom component.
public class TransitionSlider extends AnchorPane {
#FXML
private AnchorPane transitionSliderPane;
#FXML
private ImageView transitionSliderImageView;
#FXML
private Button prevButton;
#FXML
private Button nextButton;
private Map<Integer,Image> imageMap;
private Image currentImage;
private DropShadow imageViewDropShadow;
private int currentKey = 1;
private Image[] images;
public TransitionSlider() {
FXMLLoader loader = new FXMLLoader();
loader.setRoot(this);
loader.setController(this);
loader.setLocation(this.getClass().getResource("TransitionSlider.fxml"));
loader.setClassLoader(this.getClass().getClassLoader());
try {
loader.load();
} catch (IOException exception) {
throw new RuntimeException(exception);
}
prevButton.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent t) {
if(currentKey <= 1){
currentKey = currentKey + 1;
currentImage = imageMap.get(currentKey);
createTransition(transitionSliderImageView, currentImage);
}
}
});
nextButton.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent t) {
if(currentKey <= imageMap.size()){
currentKey = currentKey - 1;
currentImage = imageMap.get(currentKey);
createTransition(transitionSliderImageView, currentImage);
}
}
});
}
// more code here...
}
I want a way to capture the event and get variables inside the component and change a label outside the custom component...
for example:
public class Gallery extends Application {
#FXML
TransitionSlider ts;
Label label;
#Override
public void start(Stage stage) throws Exception {
label = new Label();
TransitionSlider ts = new TransitionSlider();
ts.captureButtonEvent(){ // need a way to capture this
label.setText(ts.getCurrentKey());
}
// more code here....
}
If I understood your question correctly, you want a binding.. Follow these steps:
1) Put bindable field and its getter/setter into TransitionSlider:
private IntegerProperty currentKey = new SimpleIntegerProperty(1);
public int getCurrentKey() {
return currentKey.get();
}
public void setCurrentKey(int val) {
return currentKey.set(val);
}
public IntegerProperty currentKeyProperty() {
return currentKey;
}
2) Bind this property to label's text in Gallery:
label = new Label();
TransitionSlider ts = new TransitionSlider();
label.textProperty.bind(ts.currentKeyProperty().asString());
Alternatively, if you want to do stuff more than just changing label's text, you can add a change listener to currentKeyProperty:
ts.currentKeyProperty().addListener(new ChangeListener<Number>() {
#Override
public void changed(ObservableValue<? extends Number> observable,
Number oldValue, Number newValue) {
label.setText(newValue);
// do other stuff according to "oldValue" and "newValue".
}
});

JavaFx Progress cannot be to solve a variable

I'm trying to put the progress to 100% after meet condition OK. But it not finds the variable "progressBar", if instead of set the progress, I set the visibility, works.
columSituacao.setCellValueFactory(new Callback<CellDataFeatures<Tabela, HBox>, ObservableValue<HBox>>() {
public ObservableValue<HBox> call(CellDataFeatures<Tabela, HBox> p) {
final Tabela tabela = p.getValue();
final ProgressBar progressBar = new ProgressBar(0.0);
progressBar.setPrefWidth(columSituacao.getWidth());
progressBar.progressProperty().bind(tabela.progressProperty());
final HBox box = new HBox();
box.setPrefHeight(Progress.PREF_HEIGHT);
final Text text = new Text();
text.textProperty().bind(tabela.etapaProperty());
final BorderPane border = new BorderPane();
border.setTop(text);
border.setBottom(progressBar);
BorderPane.setAlignment(text, Pos.CENTER);
tabela.etapaProperty().addListener(new ChangeListener<String>() {
public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
if (newValue.equals(ConstantesEtapa.ETAPA_OK)) {
progressBar.setProgress(1.0);//Here is the exception
}
}
});
box.getChildren().add(border);
return new SimpleObjectProperty<HBox>(box);
}
});
Tank's
I think your issue is that you cannot set a unidirectionally bound value.
Unbind the value before you try to set it.
For example:
if (newValue.equals(ConstantesEtapa.ETAPA_OK)) {
progressBar.progressProperty().unbind();
progressBar.setProgress(1.0);
}

Categories