Search code examples
javafxjavafx-8observablelist

JavaFX : Highlight VBox on mouse click and change color when unfocused


I want to change the background (focused) color of a VBox when I make a mouse click event and other (sibling) ones should be changed to the other (unfocused) color.

So, I coded like this belows..

First, I make a ObservableList with some VBoxes.

public class ManagerWorldController implements Initializable {

        @FXML
        private BorderPane borderPane;
        @FXML
        private AnchorPane anchorPane;
        @FXML
        private VBox menuVBox1;
        @FXML
        private VBox menuVBox2;
        @FXML
        private VBox menuVBox3;
        @FXML
        private VBox menuVBox4;
        @FXML
        private VBox menuVBox5;
        @FXML
        private VBox menuVBox6;
        @FXML
        private VBox menuVBox7;
        @FXML
        private VBox menuVBox8;
        @FXML
        private VBox menuVBox9;
        @FXML
        private VBox menuVBox10;
        @FXML
        private VBox menuVBox11;

    //    ObservableList<VBox> menuVBoxList = FXCollections
    //            .observableArrayList(menuVBox1, menuVBox2, menuVBox3, menuVBox4, menuVBox5, menuVBox6, menuVBox7, menuVBox8, menuVBox9, menuVBox10, menuVBox11);

        @Override
        public void initialize(URL url, ResourceBundle rb) {
            // TODO

        }

        @FXML
        private void handleHyperLinkOnAction(MouseEvent event) {
            if (event.getSource().equals(menuVBox1)) {
                String viewerPath = "/managerworld/viewer/ConnectionViewer.fxml";
                changeScreenOfCenter(viewerPath, menuVBox1);
            } else if (event.getSource().equals(menuVBox2)) {
                String viewerPath = "/managerworld/viewer/ConnectionViewer.fxml";
                changeScreenOfCenter(viewerPath, menuVBox2);
            } else if (event.getSource().equals(menuVBox3)) {
                String viewerPath = "/managerworld/viewer/ConnectionViewer.fxml";
                changeScreenOfCenter(viewerPath, menuVBox3);
            } else if (event.getSource().equals(menuVBox4)) {
                String viewerPath = "/managerworld/viewer/ConnectionViewer.fxml";
                changeScreenOfCenter(viewerPath, menuVBox4);
            } else if (event.getSource().equals(menuVBox5)) {
                String viewerPath = "/managerworld/viewer/ConnectionViewer.fxml";
                changeScreenOfCenter(viewerPath, menuVBox5);
            } else if (event.getSource().equals(menuVBox6)) {
                String viewerPath = "/managerworld/viewer/ConnectionViewer.fxml";
                changeScreenOfCenter(viewerPath, menuVBox6);
            } else if (event.getSource().equals(menuVBox7)) {
                String viewerPath = "/managerworld/viewer/ConnectionViewer.fxml";
                changeScreenOfCenter(viewerPath, menuVBox7);
            } else if (event.getSource().equals(menuVBox8)) {
                String viewerPath = "/managerworld/viewer/ConnectionViewer.fxml";
                changeScreenOfCenter(viewerPath, menuVBox8);
            } else if (event.getSource().equals(menuVBox9)) {
                String viewerPath = "/managerworld/viewer/ConnectionViewer.fxml";
                changeScreenOfCenter(viewerPath, menuVBox9);
            } else if (event.getSource().equals(menuVBox10)) {
                String viewerPath = "/managerworld/viewer/ConnectionViewer.fxml";
                changeScreenOfCenter(viewerPath, menuVBox10);
            } else if (event.getSource().equals(menuVBox11)) {
                String viewerPath = "/managerworld/viewer/ConnectionViewer.fxml";
                changeScreenOfCenter(viewerPath, menuVBox11);
            } else {
            }

        }

        private void changeScreenOfCenter(String path, VBox menuVBox) {
            VBox getVbox = menuVBox;
            try {
                anchorPane = FXMLLoader.load(getClass().getResource(path));
            } catch (Exception e) {
                System.out.println(e.getStackTrace().toString());
                System.out.println(e.getMessage());
            }
    //        for (VBox vbox : this.menuVBoxList) {
    //            System.out.println(vbox.getId());
    //            if (vbox.getId().equals(getVbox.getId())) {
    //                menuVBox.setStyle("-fx-background-color: #D3D3D3");
    //            } else {
    //                //Change the background color to white on other VBoxes..
    //            }
    //        }
            menuVBox.setStyle("-fx-background-color: #D3D3D3");
            borderPane.setCenter(anchorPane);
        }

    }

however, once I click menuVBox1, null pointer exception occurs.

Executing G:\JamesProjects\ManagerWorld\dist\run1616043779\ManagerWorld.jar using platform C:\Program Files\Java\jdk1.8.0_40\jre/bin/java
Exception in thread "JavaFX Application Thread" java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
    at javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1770)
    at javafx.fxml.FXMLLoader$ControllerMethodEventHandler.handle(FXMLLoader.java:1653)
    at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86)
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
    at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
    at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
    at javafx.event.Event.fireEvent(Event.java:198)
    at javafx.scene.Scene$ClickGenerator.postProcess(Scene.java:3471)
    at javafx.scene.Scene$ClickGenerator.access$8100(Scene.java:3399)
    at javafx.scene.Scene$MouseHandler.process(Scene.java:3767)
    at javafx.scene.Scene$MouseHandler.access$1500(Scene.java:3486)
    at javafx.scene.Scene.impl_processMouseEvent(Scene.java:1762)
    at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2495)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:350)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:275)
    at java.security.AccessController.doPrivileged(Native Method)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$350(GlassViewEventHandler.java:385)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler$$Lambda$148/1745970415.get(Unknown Source)
    at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:404)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:384)
    at com.sun.glass.ui.View.handleMouseEvent(View.java:555)
    at com.sun.glass.ui.View.notifyMouse(View.java:927)
    at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
    at com.sun.glass.ui.win.WinApplication.lambda$null$145(WinApplication.java:101)
    at com.sun.glass.ui.win.WinApplication$$Lambda$36/1963387170.run(Unknown Source)
    at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at sun.reflect.misc.Trampoline.invoke(MethodUtil.java:71)
    at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at sun.reflect.misc.MethodUtil.invoke(MethodUtil.java:275)
    at javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1765)
    ... 31 more
Caused by: java.lang.NullPointerException
    at managerworld.controller.ManagerWorldController.changeScreenOfCenter(ManagerWorldController.java:111)
    at managerworld.controller.ManagerWorldController.handleHyperLinkOnAction(ManagerWorldController.java:66)
    ... 41 more

pleas help me this..


Solution

  • Since your posted code is not complete to run for testing, I coded a simple demo app that shows how vbox can be styled on mouse click regarding your requirement in the question. Please spend some time to understand and port these to your own app.

    public class VBoxHighlightOnClickDemo extends Application
    {
        // vboxes
        private VBox menuVBox1 = new VBox( new Label( "menuVBox1" ) );
        private VBox menuVBox2 = new VBox( new Label( "menuVBox2" ) );
        private VBox menuVBox3 = new VBox( new Label( "menuVBox3" ) );
        private VBox menuVBox4 = new VBox( new Label( "menuVBox4" ) );
        private VBox menuVBox5 = new VBox( new Label( "menuVBox5" ) );
    
        // parent vbox that includes all vboxes
        private VBox parentVBox = new VBox( 10, menuVBox1, menuVBox2, menuVBox3, menuVBox4, menuVBox5 );
    
        // styles used for vboxes
        private final Background focusBackground = new Background( new BackgroundFill( Color.BLUEVIOLET, CornerRadii.EMPTY, Insets.EMPTY ) );
        private final Background unfocusBackground = new Background( new BackgroundFill( Color.WHITE, CornerRadii.EMPTY, Insets.EMPTY ) );
        private final Border border = new Border( new BorderStroke( Color.BLUE, BorderStrokeStyle.SOLID, null, null ) );
    
    
        @Override
        public void start( Stage primaryStage )
        {
            boxifyVBoxes();
            Scene scene = new Scene( new HBox( parentVBox ), 300, 300 );
            primaryStage.setScene( scene );
            primaryStage.show();
        }
    
    
        private void boxifyVBoxes()
        {
            for ( Node child : parentVBox.getChildren() )
            {
                VBox vb = ( VBox ) child;
                vb.setPadding( new Insets( 10 ) );
                vb.setBorder( border );
    
                // when vbox is clicked focus on it
                vb.setOnMouseClicked( ( e ) ->
                {
                    vb.requestFocus();
                } );
    
                // use different backgrounds for focused and unfocused states
                vb.backgroundProperty().bind( Bindings
                        .when( vb.focusedProperty() )
                        .then( focusBackground )
                        .otherwise( unfocusBackground )
                );
    
            }
        }
    
        public static void main( String[] args )
        {
            launch( args );
        }
    
    }
    

    Output:

    enter image description here