6 Replies Latest reply: Nov 29, 2012 2:51 AM by dscarminiabielefeld RSS

    getWidth() and getHeight() weird behaviour?

    dscarminiabielefeld
      Okay guys, what am i doing wrong here.
      Group myGroup;
      Label CompassLabel;
      //  doing new for all.
      
      //add label to the group.
      myGroup.getChildren().add(CompassLabel);
      CompassLabel.setText("360");
      So i have a label and add it to a group.

      Then i do this:
       System.out.println(CompassLabel.getWidth() + CompassLabel.getHeight());
      both return the value 0.0

      if i do this:
      Node nodeN = myGroup.getChildren().get(0); //The Label
      if (nodeN instanceof Label)
      {
                              Label label = (Label) nodeN;
                              System.out.println(label.getWidth() + label.getHeight());
      }
      it gives:
      26.27734375 // Returned Value for width
      32.27734375 // returned Value for height
      Why is that? Thanks, regards.
        • 1. Re: getWidth() and getHeight() weird behaviour?
          MiPa
          That's difficult to tell from this little code piece but I assume that your group has not yet been attached to a scene or has not yet been layed out. This only happens on a pulse and not at the moment when you attach it.
          • 2. Re: getWidth() and getHeight() weird behaviour?
            dscarminiabielefeld
            Hey Thanks.
            I can see the label on my Scene, so it's there.
            And between my first output and the second is like no other code.
            And it's pretty much the same object, isn't it?

            Can you give me some functions to check if there is something wrong?
            Can give you more code tho.
             public ViewPort()
                {
                    Compass              = new Circle();
                    LineGroup           = new Group();
                    
                    LineGroup.getChildren().add(Compass);
                    getChildren().add(LineGroup);
                    
                    for(int i = 15; i < 375;)
                    {
                        CompassLine = new Line();
                        CompassLabel = new Label(Integer.toString(i));
            
                        LineGroup.getChildren().add(CompassLine);
                        LineGroup.getChildren().add(CompassLabel);
                        
                        xStart = Compass.getCenterX() + ((Compass.getRadius() - 30) * Math.sin( i * ((2 * Math.PI) / 360)) );
                        xStart2 = Compass.getCenterX() + ((Compass.getRadius() - 15) * Math.sin( i * ((2 * Math.PI) / 360)) );
                        CompassLine.setStartX(xStart2);
                        
                        yStart = Compass.getCenterY() - ((Compass.getRadius() - 30) * Math.cos( i * ((2 * Math.PI) / 360)) );
                        yStart2 = Compass.getCenterY() - ((Compass.getRadius() - 15) * Math.cos( i * ((2 * Math.PI) / 360)) );
                        CompassLine.setStartY(yStart2);
                        
                        xEnd = Compass.getCenterX() + (Compass.getRadius() * Math.sin(i * ((2 * Math.PI) / 360)) );
                        CompassLine.setEndX(xEnd);
                        
                        yEnd = Compass.getCenterY() - (Compass.getRadius() * Math.cos(i * ((2 * Math.PI) / 360)) );
                        CompassLine.setEndY(yEnd);
                        
                        CompassLabel.setLayoutX(xStart - (CompassLabel.getWidth() / 2));
                        CompassLabel.setLayoutY(yStart - (CompassLabel.getHeight() / 2));
                        
            /*
            * Below it gives 0.0
            /*
                        Node myNode = CompassLabel;
                        Label myLabel = (Label) myNode;
                        System.out.println(myLabel.getWidth() + myLabel.getHeight());
                        
                        i = i + 15;
                    }
                    
                    (TrainingsAnimation.getInstance().radarStage.widthProperty()).addListener(new ChangeListener()
                    {
                        @Override
                        public void changed(ObservableValue arg0, Object arg1, Object arg2)
                        {
                             newStageWdith.set(getWidth());
                             Compass.setCenterX(newStageWdith.getValue() / 2);
                             Compass.setRadius(TrainingsAnimation.getInstance().radarStage.getWidth() / 2 );
                        }                   
                    });   
                    
                    (TrainingsAnimation.getInstance().radarStage.widthProperty()).addListener(new ChangeListener()
                    {
                        @Override
                        public void changed(ObservableValue arg0, Object arg1, Object arg2)
                        {
                            newStageHeight.set(getHeight());
                            Compass.setCenterY(newStageHeight.getValue() / 2);
            
                            for(int i = 0; i < LineGroup.getChildren().size(); i++)
                            {
                                Node nodeN = LineGroup.getChildren().get(i);
                                if (nodeN instanceof Line)
                                {
                                    // Set new points for Line(actLine);
                                    actLine++;
                                    alpha = actLine * 15; 
                                    
                                    Line line = (Line)nodeN;
                                    xStart = Compass.getCenterX() + ((Compass.getRadius() - 30) * Math.sin( alpha * ((2 * Math.PI) / 360)) );
                                    xStart2 = Compass.getCenterX() + ((Compass.getRadius() - 15) * Math.sin( alpha * ((2 * Math.PI) / 360)) );
                                    line.setStartX(xStart2);
                                    yStart = Compass.getCenterY() - ((Compass.getRadius() - 30) * Math.cos( alpha * ((2 * Math.PI) / 360)) );
                                    yStart2 = Compass.getCenterY() - ((Compass.getRadius() - 15) * Math.cos( alpha * ((2 * Math.PI) / 360)) );;
                                    line.setStartY(yStart2);
                        
                                    xEnd = Compass.getCenterX() + (Compass.getRadius() * Math.sin(alpha * ((2 * Math.PI) / 360)));
                                    line.setEndX(xEnd);
                                    
                                    yEnd = Compass.getCenterY() - (Compass.getRadius() * Math.cos(alpha * ((2 * Math.PI) / 360)) );
                                    line.setEndY(yEnd);
                                }
                                else if (nodeN instanceof Label)
                                {
                                    Label label = (Label)nodeN;
                                    label.setLayoutX(xStart - (label.getWidth() / 2) ) ;
                                    label.setLayoutY(yStart - (label.getHeight() / 2) ); 
            /*
            * here are the correct height and width
            */
                                    System.out.println(label.getWidth() + label.getHeight());
                                }
                            }
                            Compass.setRadius(TrainingsAnimation.getInstance().radarStage.getHeight() / 2 );
                        }                  
                    });   
                }
            Think this is to confusing and unclear to read, but maybe you see the mistake. i wrote a comment on the two ouputs.
            • 3. Re: getWidth() and getHeight() weird behaviour?
              jsmith
              MiPa is correct.

              After you create the label and before you query it's dimensions, you don't relinquish control to the JavaFX runtime to allow it to do a rendering pulse on the label which will set it's height and width properties. The rendering pulse is required because the Label's dimensions will depend on stuff like it's inherited css attributes which are calculated during the pulse processing.

              You could use a binding statement - quick and easy for one a small number of relationships.
              CompassLabel.layoutXProperty.bind(new SimpleDoubleProperty(xStart).subtract(CompassLabel.widthProperty().divide(2)));  // not compiled code you might need to tweak it for syntax errors.
              Or subclass Group, override layoutChildren and do your layout code in there, making use of stuff like the prefWidth calculations. This is good if you want to create your own control like components
              http://docs.oracle.com/javafx/2/api/javafx/scene/Group.html#layoutChildren()
              http://docs.oracle.com/javafx/2/api/javafx/scene/Group.html#prefWidth(double)

              Or you can redo your layout so that it doesn't depend on the width.

              Or, instead of a dumb Group, you can use a layout manager like a VBox which automatically handles layout resizing and placement issues for you after you have set it up with content and relevant constraints. This is the preferred solution in many cases

              Or you can delay querying the width until you are sure that node has been rendered. For example, for an initial scene creation - after a stage.show() method is called. Or perhaps listening for the pulse to occur or on finishing a delay Timeline (though I wouldn't recommend the pulse listener or timeline approach if it can be avoided).
              • 4. Re: getWidth() and getHeight() weird behaviour?
                dscarminiabielefeld
                Sounds good, thank you very much. ;-)
                • 5. Re: getWidth() and getHeight() weird behaviour?
                  MiPa
                  So my answer was not even helpful - that makes me think :-)
                  • 6. Re: getWidth() and getHeight() weird behaviour?
                    dscarminiabielefeld
                    Haha, oh snap. How rude of me! ;-)
                    Of course it was - Thank you too MiPa! :-D