Trouble with the JAVAFX lines - just 1 line has been drawn

321 Views Asked by At

IMAGE OF GUI - As you see in the picture I have clicked on three citys (sion, sarnen and bellinzona) but I didn't get 3 lines as expected (it should be a triangle). I've got an exception named java.lang.IllegalArgumentException. In the for-loop I am creating duplicates (children) and then I thought of a solution named boolean-checking but that doesn't work (just 1 line drawn).

Here is the code of the controller - Look up to function handleButtonAction()

package tsprealone;

import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.RadioButton;
import javafx.scene.shape.Line;
import javafx.scene.image.ImageView;
import javafx.scene.layout.AnchorPane;

/**
 *
 * @author kbwschuler
 */
public class FXMLDocumentController implements Initializable {

    @FXML
    private AnchorPane anchorPane;
    @FXML
    private ImageView img;

    @FXML
    private ArrayList<Stadt> stadte = new ArrayList<Stadt>();
    @FXML
    private ArrayList<Line> lines = new ArrayList<Line>();
    @FXML
    private Button test;
    @FXML
    private RadioButton zug;
    @FXML
    private RadioButton zurich;
    @FXML
    private RadioButton schaffhausen;
    @FXML
    private RadioButton stgallen;
    @FXML
    private RadioButton aarau;
    @FXML
    private RadioButton chur;
    @FXML
    private RadioButton glarus;
    @FXML
    private RadioButton frauenfeld;
    @FXML
    private RadioButton schwyz;
    @FXML
    private RadioButton luzern;
    @FXML
    private RadioButton sarnen;
    @FXML
    private RadioButton bellinzona;
    @FXML
    private RadioButton sion;
    @FXML
    private RadioButton liestal;
    @FXML
    private RadioButton bern;
    @FXML
    private RadioButton delemont;
    @FXML
    private RadioButton solothurn;
    @FXML
    private RadioButton fribourg;
    @FXML
    private RadioButton neuchatel;
    @FXML
    private RadioButton lausanne;
    @FXML
    private RadioButton genf;
    @FXML
    private RadioButton altdorf;
    @FXML
    private RadioButton stans;
    @FXML
    private RadioButton basel;
    @FXML
    private RadioButton appenzell;
    @FXML
    private RadioButton herisau;
    private ArrayList<Stadt> ausgewaehlt = new ArrayList<Stadt>(); //check if is checked

    @FXML
    private void handleButtonAction(ActionEvent event) {
        addCities();
        for (Stadt stadt : stadte) {
            if (stadt.isIsClicked()) {
                ausgewaehlt.add(stadt);
            }
        }
        boolean added = false;
        starter();
        for (Stadt stadt : ausgewaehlt) {
            System.out.println(stadt.getName());
            for(Line line: lines)
            {

                if(!added)
                {
                    anchorPane.getChildren().addAll(line);
                    added = true;
                    System.out.println(line);

                }

            }





        }
    }

    public void addCities(){

        stadte.add(new Stadt("Zug", zug.getLayoutX(), zug.getLayoutY(), check(zug)));
        stadte.add(new Stadt("Zurich", zurich.getLayoutX(), zurich.getLayoutY(), check(zurich)));
        stadte.add(new Stadt("Schaffhausen", schaffhausen.getLayoutX(), schaffhausen.getLayoutY(), check(schaffhausen)));
        stadte.add(new Stadt("Aarau", aarau.getLayoutX(), aarau.getLayoutY(), check(aarau)));
        stadte.add(new Stadt("Chur", chur.getLayoutX(), chur.getLayoutY(), check(chur)));
        stadte.add(new Stadt("Glarus", glarus.getLayoutX(), glarus.getLayoutY(), check(glarus)));
        stadte.add(new Stadt("Frauenfeld", frauenfeld.getLayoutX(), frauenfeld.getLayoutY(), check(frauenfeld)));
        stadte.add(new Stadt("Schwyz", schwyz.getLayoutX(), schwyz.getLayoutY(), check(schwyz)));
        stadte.add(new Stadt("Luzern", luzern.getLayoutX(), luzern.getLayoutY(), check(luzern)));
        stadte.add(new Stadt("Sarnen", sarnen.getLayoutX(), sarnen.getLayoutY(), check(sarnen)));
        stadte.add(new Stadt("Bellinzona", bellinzona.getLayoutX(), bellinzona.getLayoutY(), check(bellinzona)));
        stadte.add(new Stadt("Sion", sion.getLayoutX(), sion.getLayoutY(), check(sion)));
        stadte.add(new Stadt("Liestal", liestal.getLayoutX(), liestal.getLayoutY(), check(liestal)));
        stadte.add(new Stadt("Bern", bern.getLayoutX(), bern.getLayoutY(), check(bern)));
        stadte.add(new Stadt("Delemont", delemont.getLayoutX(), delemont.getLayoutY(), check(delemont)));
        stadte.add(new Stadt("Solothurn", solothurn.getLayoutX(), solothurn.getLayoutY(), check(solothurn)));
        stadte.add(new Stadt("Fribourg", fribourg.getLayoutX(), fribourg.getLayoutY(), check(fribourg)));
        stadte.add(new Stadt("Neuchatel", neuchatel.getLayoutX(), neuchatel.getLayoutY(), check(neuchatel)));
        stadte.add(new Stadt("Lausanne", lausanne.getLayoutX(), lausanne.getLayoutY(), check(lausanne)));
        stadte.add(new Stadt("Genf", genf.getLayoutX(), genf.getLayoutY(), check(genf)));
        stadte.add(new Stadt("Altdorf", altdorf.getLayoutX(), altdorf.getLayoutY(), check(altdorf)));
        stadte.add(new Stadt("Stans", stans.getLayoutX(), stans.getLayoutY(), check(stans)));
        stadte.add(new Stadt("Basel", basel.getLayoutX(), basel.getLayoutY(), check(basel)));
        stadte.add(new Stadt("Appenzell", appenzell.getLayoutX(), appenzell.getLayoutY(), check(appenzell)));
        stadte.add(new Stadt("Herisau", herisau.getLayoutX(), herisau.getLayoutY(), check(herisau)));
        stadte.add(new Stadt("St Gallen", stgallen.getLayoutX(), stgallen.getLayoutY(), check(stgallen)));

    }

    public void starter() {

        for(int i = 0; i<ausgewaehlt.size(); i++)
        {
                if(i != ausgewaehlt.size() - 1){ 

                    lines.add(new Line(ausgewaehlt.get(i).getxCoord(), ausgewaehlt.get(i).getyCoord(), ausgewaehlt.get(i+1).getxCoord(), ausgewaehlt.get(i+1).getyCoord()));
                }else {
                    lines.add(new Line(ausgewaehlt.get(i).getxCoord(), ausgewaehlt.get(i).getyCoord(), ausgewaehlt.get(0).getxCoord(), ausgewaehlt.get(0).getyCoord()));
                }

        }



    }

    public boolean check(RadioButton rb) {
        if (rb.isSelected()) {
            return true;
        } else {
            return false;
        }
    }

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        addCities();
        starter();
    }

}

PS: I've tried to make two buttons .. one for storing the selected radiobuttons and add it to the array list "ausgewaehlt" and another one for creating the lines but that didn't work

1

There are 1 best solutions below

0
On

First of all you do not remove any Lines once they are added. This will probably lead to problems later.

Furthermore you add the cities over and over again for some reason. Doing this once should be enough (or clear at least clear the list).

private final Set<Line> connections = new HashSet<>();

private void connect(Stadt city1, Stadt city2) {
    Line line = new Line(city1.getxCoord(), city1.getyCoord(), city2.getxCoord(), city2.getyCoord());
    anchorPane.getChildren().addAll(line);
    connections.add(line);
}

@FXML
private void handleButtonAction(ActionEvent event) {
    // remove old connections
    anchorPane.getChildren().removeAll(connections);
    connections.clear();

    findSelectedCities();

    if (stadte.size() >= 2) {
        // connect selected cities
        Iterator<Stadt> iter = stadte.iterator();
        Stadt city = iter.next();
        while (iter.hasNext()) {
            Stadt nextCity = iter.next();
            connect(city, nextCity);
            city = nextCity;
        }

        if (stadte.size() >= 3) {
            // connect to start, if there are more than 2 selected cities 
            connect(city, stadte.get(0));
        }
    }
}

private void addSelectedCity(String name, RadioButton radio) {
    if (radio.isSelected()) {
        stadte.add(new Stadt(name, radio.getLayoutX(), radio.getLayoutY(), true));
    }
}

private void findSelectedCities() {
    stadte.clear();
    addSelectedCity("Zug", zug);
    addSelectedCity("Zurich", zurich);
    ...
}

Note that this will not preserve the order of selection. To do that you should instead add a listener to the onAction event for the RadioButtons and add/remove them from the stadte list...

private void refreshConnections() {
    // remove old connections
    anchorPane.getChildren().removeAll(connections);
    connections.clear();

    if (stadte.size() >= 2) {
        // connect selected cities
        Iterator<Stadt> iter = stadte.iterator();
        Stadt city = iter.next();
        while (iter.hasNext()) {
            Stadt nextCity = iter.next();
            connect(city, nextCity);
            city = nextCity;
        }

        if (stadte.size() >= 3) {
            // connect to start, if there are more than 2 selected cities 
            connect(city, stadte.get(0));
        }
    }
}

@FXML
private handleSelectionChange(ActionEvent event) {
    ToggleButton button = (ToggleButton) event.getSource();
    Stadt city = (Stadt) button.getUserData();

    if (button.isSelected()) {
        stadte.add(city);
    } else {
        stadte.remove(city);
    }
    refreshConnections();
}

private void addCity(String name, RadioButton radio) {
    Stadt city = new Stadt(name, radio.getLayoutX(), radio.getLayoutY(), radio.isSelected());
    stadte.add(city);
    radio.setUserData(city);
}

public void addCities(){
    addCity("Zug", zug);
    addCity("Zurich", zurich);
    ...
}