0

I simply try to program a slidebar, which contains a inloaded fxml. These FXML is my menu. With this Menu I have to load other FXML files in a special pane without using a thread-liked working background to request or produce an update.

my SlideOut.java (run):`package slideout;

import java.io.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.animation.*;
import javafx.application.Application;
import javafx.event.*;
import javafx.fxml.FXMLLoader;
import javafx.geometry.Pos;
import javafx.scene.*;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.scene.text.Text;
import javafx.scene.web.WebView;
import javafx.stage.Stage;
import javafx.util.Duration;
import javafx.scene.web.WebEngine;

/**
 * Example of a sidebar that slides in and out of view
 */
public class SlideOut extends Application {

    public String mainConntent;
    String currentPage;
    Pane mainView;
    Stage staged;

    public void changeConntent(String Conntent){
        FXMLLoader fxmlMainLoader = new FXMLLoader(getClass().getResource(Conntent));
        try {
            mainView = (Pane) fxmlMainLoader.load();
        } catch (IOException ex) {
            Logger.getLogger(SlideOut.class.getName()).log(Level.SEVERE, null, ex);
        }
        mainView.setPrefSize(800, 600);

// create a sidebar with some content in it.

        final Pane lyricPane = createSidebarContent();
        SideBar sidebar = new SideBar(250, lyricPane);
        VBox.setVgrow(lyricPane, Priority.ALWAYS);

// layout the scene.
        final BorderPane layout = new BorderPane();
        Pane mainPane = VBoxBuilder.create().spacing(10)
                .children(
                        sidebar.getControlButton(),
                        mainView
                ).build();
        layout.setLeft(sidebar);
        layout.setCenter(mainPane);

// show the scene

        Scene scene = new Scene(layout);
        scene.getStylesheets().add(getClass().getResource("slideout.css").toExternalForm());
        staged.setScene(scene);
        staged.showAndWait();
         }





    public static void main(String[] args) throws Exception {
        launch(args);
    }

    public void start(final Stage stage){

        stage.setTitle("SLideOutExample");

// create a WebView to show to the right of the SideBar.
        mainView = new Pane();

        FXMLLoader fxmlMainLoader = new FXMLLoader(getClass().getResource("Home.fxml"));
        try {
            mainView = (Pane) fxmlMainLoader.load();
        } catch (IOException ex) {
            Logger.getLogger(SlideOut.class.getName()).log(Level.SEVERE, null, ex);
        }
        mainView.setPrefSize(800, 600);

// create a sidebar with some content in it

        final Pane lyricPane = createSidebarContent();
        SideBar sidebar = new SideBar(250, lyricPane);
        VBox.setVgrow(lyricPane, Priority.ALWAYS);

// layout the scene

        final BorderPane layout = new BorderPane();
        Pane mainPane = VBoxBuilder.create().spacing(10)
                .children(
                        sidebar.getControlButton(),
                        mainView
                ).build();
        layout.setLeft(sidebar);
        layout.setCenter(mainPane);

// show the scene

        Scene scene = new Scene(layout);
        scene.getStylesheets().add(getClass().getResource("slideout.css").toExternalForm());
        stage.setScene(scene);
        stage.show();//showAndWait();? and something to do?

    }

    private BorderPane createSidebarContent() {// create some content to put in the sidebar.
        final BorderPane lyricPane = new BorderPane();
        FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("SlideBarConntent.fxml"));
        Pane cmdPane = null;
        try {
            cmdPane = (Pane) fxmlLoader.load();
        } catch (IOException ex) {
            Logger.getLogger(SlideOut.class.getName()).log(Level.SEVERE, null, ex);
        }

        try {
            lyricPane.setCenter(cmdPane);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return lyricPane;
    }

    /**
     * Animates a node on and off screen to the left.
     */
    class SideBar extends VBox {

        /**
         * @return a control button to hide and show the sidebar
         */
        public Button getControlButton() {
            return controlButton;
        }
        private final Button controlButton;

        /**
         * creates a sidebar containing a vertical alignment of the given nodes
         */
        SideBar(final double expandedWidth, Node... nodes) {
            getStyleClass().add("sidebar");
            this.setPrefWidth(expandedWidth);
            this.setMinWidth(0);

// create a bar to hide and show.
            setAlignment(Pos.CENTER);
            getChildren().addAll(nodes);

// create a button to hide and show the sidebar.
            controlButton = new Button("Collapse");
            controlButton.getStyleClass().add("hide-left");
            controlButton.setId("ControlButton");

// apply the animations when the button is pressed

            controlButton.setOnAction(new EventHandler<ActionEvent>() {
                @Override
                public void handle(ActionEvent actionEvent) {
// create an animation to hide sidebar

                    final Animation hideSidebar = new Transition() {
                        {
                            setCycleDuration(Duration.millis(250));
                        }

                        protected void interpolate(double frac) {
                            final double curWidth = expandedWidth * (1.0 - frac);
                            setPrefWidth(curWidth);
                            setTranslateX(-expandedWidth + curWidth);
                        }
                    };
                    hideSidebar.onFinishedProperty().set(new EventHandler<ActionEvent>() {
                        @Override
                        public void handle(ActionEvent actionEvent) {
                            setVisible(false);
                            controlButton.setText("Show");
                            controlButton.getStyleClass().remove("hide-left");
                            controlButton.getStyleClass().add("show-right");
                        }
                    });
// create an animation to show a sidebar

                    final Animation showSidebar = new Transition() {
                        {
                            setCycleDuration(Duration.millis(250));
                        }

                        protected void interpolate(double frac) {
                            final double curWidth = expandedWidth * frac;
                            setPrefWidth(curWidth);
                            setTranslateX(-expandedWidth + curWidth);
                        }
                    };
                    showSidebar.onFinishedProperty().set(new EventHandler<ActionEvent>() {
                        @Override
                        public void handle(ActionEvent actionEvent) {
                            controlButton.setText("Collapse");
                            controlButton.getStyleClass().add("hide-left");
                            controlButton.getStyleClass().remove("show-right");
                        }
                    });
                    if (showSidebar.statusProperty().get() == Animation.Status.STOPPED && hideSidebar.statusProperty().get() == Animation.Status.STOPPED) {
                        if (isVisible()) {
                            hideSidebar.play();
                        } else {
                            setVisible(true);
                            showSidebar.play();
                        }
                    }
                }
            });
        }
    }
}
`

After these I enter in the controller of my SlideBarConntent.fxml-Controller the folowing action Events:

 /*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

package slideout;

import java.net.URL;
import java.util.ResourceBundle;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.layout.Pane;

/**
 * FXML Controller class
 *
 * @author tobiasg
 */
public class SlideBarConntentController{

    SlideOut mainJava = new SlideOut();
    String Home = "Home.fxml";
    String Example = "FXMLExampelConntent.fxml";
    Pane dustbin;


     @FXML void loadHomeAction(ActionEvent event) {
        try {
            mainJava.changeConntent(Home);
        } catch (Exception ex) {
            Logger.getLogger(SlideBarConntentController.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

     @FXML void loadFXMLConntentExampleAction(ActionEvent event) {
        try {
            mainJava.changeConntent(Home);
        } catch (Exception ex) {
            Logger.getLogger(SlideBarConntentController.class.getName()).log(Level.SEVERE, null, ex);
        }
    }


}

I hope someone can help me and exuse me for my bad english skills.

xXTobiXx
  • 17
  • 5

1 Answers1

1

The reason this doesn't work is that you are creating a new instance of your SlideOut class. When you call changeContent, you are invoking it on that new instance, not on the instance that represents the application that is displayed.

I would fix this by having your SlideBarContentController expose a property for the current content. Your application can then observe this property and respond. This will also remove the coupling between the controller and the application class, which is desirable.

The controller would look like this:

import java.net.URL;
import java.util.ResourceBundle;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.layout.Pane;

/**
 * FXML Controller class
 *
 * @author tobiasg
 */
public class SlideBarConntentController{

    String Home = "Home.fxml";
    String Example = "FXMLExampelConntent.fxml";
    Pane dustbin;

    private final StringProperty content = new SimpleStringProperty(this, "content", "");

    public StringProperty contentProperty() {
        return content ;
    }
    public final String getContent() {
        return contentProperty().get();
    }
    public final void setContent(String content) {
        contentProperty().set(content);
    }

     @FXML void loadHomeAction(ActionEvent event) {
        content.set(Home);
    }

     @FXML void loadFXMLConntentExampleAction(ActionEvent event) {
        content.set(Example);
    }


}

Now in your application class, you need to access the controller and observe the property:

    FXMLLoader fxmlMainLoader = new FXMLLoader(getClass().getResource("Home.fxml"));
    try {
        mainView = (Pane) fxmlMainLoader.load();
        SlideBarContentController contentController = (SlideBarContentController) fxmlMainLoader.getController();
        contentController.contentProperty().addListener(new ChangeListener<String>() {
            @Override
            public void changed(ObservableValue<? extends String> obs, String oldValue, String newValue) {
                changeContent(newValue);
            }
        });
    } catch (IOException ex) {
        Logger.getLogger(SlideOut.class.getName()).log(Level.SEVERE, null, ex);
    }

(You will need to add a couple of imports.)

James_D
  • 201,275
  • 16
  • 291
  • 322
  • Thank you for yourOk I see the Problem, ehm but how can I update the GUI by a Event and not by a backgroundworker or something like that? because I need something which calles changeConntent(String Conntent)? Is it possible to realise this by the given Buttons (i Think no, based on the instance problem). Or shoud I use something like a refresh button? – xXTobiXx Sep 26 '14 at 07:01
  • I'm not sure I understand the question: but in the FXML if you do ``, then pressing that button will set the value of the content property. The listener you registered on the content property (in the application class) will then get triggered, so `changeContent` will get called. – James_D Sep 26 '14 at 11:56