JavaFX dodawanie Pane

0

Cześć
Uczę się JavaFX i mam pewien problem. Oprócz głównego GUI zrobiłem w pliku .fxml Pane który chciałbym wielokrotnie dodawać do GUI lecz za każdym razem trochę edytując jego dane (zmienić obrazek, zmienić tekst itd). I mam taki problem że nie wiem jak się dobrać do tych komponentów które chciałbym edytować.
Pane dodaje do GUI tak

centerVBox.getChildren().add(p);

Potrzebuję coś w rodzaju takiej metody:

    @FXML
    private ImageView img;

    @FXML
    private Label cena;

    @FXML
    private Label nazwa;

    @FXML
    private Button opisOferty;

    Pane getPane(Trip o) {
        Pane p = null;
        try {
            p = (Pane) FXMLLoader.load(getClass().getResource("SingleTripPane.fxml"));
            img.setImage(new Image("http://"));
            cena.setText("999");
            nazwa.setText("Australia");
            opisOferty.setOnAction(e -> {
                try {
                    Desktop.getDesktop().browse(new URI("http://"));
                } catch (Exception e1) {
                    e1.printStackTrace();
                }
            });

        } catch (Exception e1) {
            e1.printStackTrace();
        }
        return p;
    }

Próbowałem zrobić coś takiego w klasie kontrolera do mojego Pane ale niestety nie chce działać w ten sposób.
Załączam plik .fxml jak by ktoś chciał zerknąć.

Mógłby mi ktoś podpowiedzieć jak powinienem to zrobić ?

0

Co to znaczy "ale niestety nie chce działać w ten sposób."? Napisz coś więcej, bo trudno cokolwiek poradzić.

Generalnie widzę jeden błąd projektowy - mianowicie tworzysz obiekty typu Pane z referencją na ten sam Label i ImageView. Raczej bym to zrobił w tym stylu:


public class MyPane extends Pane {

    @FXML private Button fooButton;
    // Inne elementy

    public MyPane(){
        FXMLLoader loader = new FXMLLodader(new URL("Some URL"));
        loader.setRoot(this);
        loader.setController(this);
        try {
            loader.load();
        } catch(Exception e){
            // LOG ERROR
        }
    }
}
0

Tak najogólniej to potrzebuje zrobić taką klasę jak ta :

public class TestPane extends Pane {

    public TestPane(String s){
        Label nazwa = new Label(s);
        this.setPrefSize(450, 150);
        BorderPane borderPane = new BorderPane();
        borderPane.setCenter(nazwa);
        this.getChildren().add(borderPane);
    }
}

Tylko że elementy mają nie być tworzone w klasie tylko wczytane z pliku .fxml
Następnie zmienione wartości jakiś komponentów np. napis w Label

Spróbowałem zmodyfikować trochę twój kod:

public class MyPane extends Pane implements Initializable {

    @FXML
    private ImageView img;

    @FXML
    private Label cena;

    @FXML
    private Label nazwa;

    @FXML
    private Button opisOferty;

    public MyPane() {
        FXMLLoader loader;
        try {
            loader = new FXMLLoader(getClass().getResource("SingleTripPane.fxml"));
            loader.setRoot(this);
            loader.setController(this);
            loader.load();
        } catch (MalformedURLException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        } catch (Exception e) {
            // LOG ERROR
        }
    }
    public MyPane(Trip o){
        super();
        //img.setImage(new Image("http://cdntravelplanet.pl/53245A/NPL/sommer/miniature275x155/grecja/kreta/ammoudara/studios-la-palma_0.jpg"));
        cena.setText("999");
        nazwa.setText("Egipt");
        opisOferty.setOnAction(e -> {
            try {
                Desktop.getDesktop().browse(new URI("http://www.travelplanet.pl/wczasy/egipt/hurghada/hurghada/triton-empire,12072015ALFA11800.html?czas=7:7&wyzywienie=2&osoby=2&lotnisko=Warszawa&sortowanie=1&kolejnosc=up&dojazd=F"));
            } catch (Exception e1) {
                e1.printStackTrace();
            }
        });

    }

Niestety tutaj jak gdyby w ogóle nie został wczytany plik .fxml dlatego że przy używaniu konstruktora bezargumentowego nie ma błędów ale też nic się nie dodaje.
Natomiast używając konstruktora z argumentem dostajemy NullPointerException przy próbie zmiany jakiegoś elementu (np zmiana tekstu w Label)

0

Problem rozwiązany.
Zrobiłem tak:
Kontroler

public class SingleTripPaneController implements Initializable {

    @FXML
     ImageView img;

    @FXML
     Label cena;

    @FXML
     Label nazwa;

    @FXML
     Button opisOferty;

    @Override
    public void initialize(URL arg0, ResourceBundle arg1) {
        SingleTripPane.setControl(this);
    }

}

Tworzenie Pane

public class SingleTripPane {
    private static SingleTripPaneController control;
    private Pane p;

    public SingleTripPane(){
        Pane p = null;
        try {
            p = (Pane) FXMLLoader.load(getClass().getResource("SingleTripPane.fxml"));
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        this.p = p;
    }

    public  Pane getPane(Trip trip) {
        control.img.setImage(new Image(trip.img));
        control.cena.setText(Integer.toString(trip.price));
        control.nazwa.setText(trip.country);
        control.opisOferty.setOnAction(e -> {
            try {
                Desktop.getDesktop().browse(new URI(trip.link));
            } catch (Exception e1) {
                e1.printStackTrace();
            }
        });

        return p;

    }

    public static void setControl(SingleTripPaneController o){
        control = o;
    }

}
0

W takim razie robisz to źle :)

Najprościej z Twojego punktu widzenia będzie użyć atrybutu fx:controller. Idąc za tutorialem z tej strony:
https://docs.oracle.com/javaf[...]les/introduction_to_fxml.html

Kontroler możesz zadeklarować w FXMLu:

<VBox fx:controller="com.foo.MyController"
    xmlns:fx="http://javafx.com/fxml">
    <children>
        <Button text="Click Me!" onAction="#handleButtonAction"/>
    </children>
</VBox>

I później w dostępnym Classpath projektu dodajesz:

package com.foo;

public class MyController {
    public void handleButtonAction(ActionEvent event) {
        System.out.println("You clicked me!");
    }
}

Z doświadczenia wiem, że problemy się zaczynają, gdy masz kilka ekranów i chciałbyś zrobić pomiędzy nimi zależności - wtedy trzeba ALBO wyłuskiwać kontrolery podczas ładowania FXMLa, albo pójść na odwrót - przed ładowaniem FXMLa trzeba loaderowi wskazać już gotowy kontroler.

Ale w Twoim przypadku to powinno spokojnie wystarczyć.

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0