2016-07-06 4 views
0

Я работаю над проектом, для которого требуется «отображаемое» представление VBoxes. Моя иерархическая компоновка приложения - GridPane -> VBox (в одной из ячеек) -> VBoxes (которые отображают разные наборы данных друг на друга) -> Данные. У меня есть две сцены.JavaFX: динамически добавленный VBox не отображается

Данные отображаются на Сцене 1. Пользователь может добавлять данные через форму и щелкая по кнопке на Сцене 2. Затем добавленные данные должны отображаться под существующими данными как VBox внутри родительского VBox на Сцене 1 снова.

Вот код, который станет ясно:

My Scene 1 .fxml файл выглядит следующим образом (упрощенный):

<GridPane fx:id="grid" fx:controller="application.Controller"> 
    [here: ColumnConstraints] 
    <children> 
    <VBox fx:id="parentBox" GridPane.columnIndex="0" GridPane.rowIndex="1"/> 
    <Button fx:id="goToScene2" text="+" onAction="#goToScene2"/> 
    </children> 
</GridPane> 

Сцена 2 просто имеет кнопку и TextField:

<GridPane fx:id="grid" fx:controller="application.AddDataController"> 
    [here: ColumnConstraints] 
    <children> 
    <Button fx:id="addData" text="add" onAction="#bAddData"/> 
    <TextField fx:id="data"/> 
    </children> 
</GridPane> 

My Scene 1 контроллер (контроллер) выглядит следующим образом:

public class Controller implements Initializable { 
    @FXML Button goToScene2; 
    @FXML VBox parentBox; 

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

    public void addData(String s) { 
    Label lbl = new Label(s); 
    VBox dataBox = new VBox(); 
    dataBox.setPadding(new Insets(15, 5, 15, 5)); 
    dataBox.setSpacing(5); 
    dataBox.setMaxHeight(80); 
    dataBox.getChildren().add(lbl); 
    parentBox.getChildren().add(dataBox); 
    } 
} 

Это так, потому что в DataBox содержится больше элементов, чем на этикетке, но это не похоже на меня в этом контексте.

My Scene 2 контроллер (addDataController) выглядит следующим образом:

@FXML Button addData; 
@FXML TextField data; 

@FXML protected void bAddData(){ 
    String content = data.getText();  
    FXMLLoader fxmlLoader = new FXMLLoader(); 
    Pane p = fxmlLoader.load(getClass().getResource("scn1.fxml").openStream()); 
    Controller cont = (Controller) fxmlLoader.getController(); 

    cont.addData(content); 
} 

Таким образом, когда один нажимает на-Data-Button Добавить в Scene 2, инициируемый метод передает введенные данные на контроллер сцены 1. Это связано с тем, что новые данные должны отображаться в Сцене 1 сейчас.

Я чувствую, что логика не работает (отредактировано здесь), потому что, когда я прошу

System.out.println(parentBox.getChildren().size(); 

до и после добавления данных, он всегда имеет один ребенок, даже если она должна иметь один подробнее ...

Если я искусственно заполняю String-Array и перемещаю все из addData в (String s) в Initialize (...), он работает, и данные отображаются как VBoxes в родительском VBox.

Я не публиковал основной класс, потому что загрузка контроллеров и изменение сцены не являются проблемой.

Благодарим всех вас за помощь! :)

+1

Я не верю, что экземпляр 'Controller const', который вы используете для вызова' AddData (content) 'with, представляет собой тот же экземпляр' Controller', который использует ваша основная 'Scene'. «FXMLLoader» создает новый экземпляр, который не находится в графе сцены. Простое исправление может состоять в том, чтобы передать главный контроллер сцены во вторую сцену. Как выглядит ваш метод goToScene? – OttPrime

+0

Это на самом деле то, чего я не видел таким образом. Однако используемый Контроллер определен в файле .fxml, поэтому я не могу получить к нему доступ из какого-либо другого класса. Он никогда не загружался в код JavaFX. Создание классов контроллеров static также не сработало. – s4inz

+0

Извините за это. Метод goToScene вызывает метод в основном классе программы и передает строку. Эта строка обрабатывается в операторе switch-case и запускает 'currentStage.setScene (newScene)'. – s4inz

ответ

0

Просто чтобы предоставить более подробную информацию, вместе с идеей, что я не знаю, как ее реализовать.

Это мой основной класс:

@Override 
public void start(Stage primaryStage) { 
    currentStage = primaryStage; 
    Parent root = FXMLLoader.load(getClass().getResource("Scene1.fxml")); 
    scene1 = new Scene(root); 
} 

Могу ли я загрузить контроллер в этой точке и сделать поглотитель, который проходит контроллер? Поэтому у меня будет только один экземпляр этой программы.

Я попытался вставку:

FXMLLoader fxmlLoader = new FXMLLoader(); 
fxmlLoader.load(getClass().getResource("Scene1.fxml").openStream()); 
Controller controller = (Controller) fxmlLoader.getController(); 

после строки

Parent root ... 

. Но это дважды загружает XML-файл. Как я могу соединять обе части?

Большое спасибо за терпение!

EDIT ::::::::: Следующий код работает для меня:

@Override 
public void start(Stage primaryStage) { 
    currentStage = primaryStage; 
    FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("Scene1.fxml")); 
    Parent root =(Parent) fxmlLoader.load(); 
    controller = (Controller) fxmlLoader.getController(); 
} 

Теперь я могу задать главный класс controller и она всегда проходит, что один экземпляр.

Благодарим за то, что вы указали меня в правильном направлении! :)

Смежные вопросы