This discussion is archived
3 Replies Latest reply: Jan 14, 2013 10:39 AM by 921640 RSS

Positioning the Popup control on the Stage (Notification control)

921640 Newbie
Currently Being Moderated
Hello everybody.

I'm trying to create a JFX control that will provide an easy way to show notifications (i.e. Notification control). This control extends the javafx.stage.Popup (full code on https://bitbucket.org/scekics/jfxnotification ) and everything is looking good - except positioning.

I've tried to override the
public void show(Window owner)
method so that Notification by default positions itself in the top center area of the Stage/Scene (the most logical place, in my opinion), but I just can't get it right. I've tried different formulas, properties, Scene and Stage-based calculations, but in wain.

This is the current method:
@Override
    public void show(Window window) {
        Double sceneLayoutX=window.getScene().getRoot().getLayoutX();
        Double sceneY=window.getScene().getY();
        Double sceneWidth=window.getScene().getWidth();
        Double windowWidth=window.getWidth();
        Double myX;
        myX=(windowWidth/2.0)-300.0+sceneLayoutX;
        setX(myX);
        setY(sceneY+30.0);
        super.show(window);
        initAutomaticClosing();
}
Please note that these hard-coded dimensions were an act of a desperate man - so don't judge. :)

Every recommendation (regarding this problem and the Notification control in general) is welcome. Thank you!

Edited by: scekics on Jan 13, 2013 4:27 AM - Corrected URL
  • 1. Re: Positioning the Popup control on the Stage (Notification control)
    984080 Explorer
    Currently Being Moderated
    My way to handle pop-ups, is with a StackPane as base element.

    Simple use .add(...popup-element) on the stackpane.
    The set with VAlignment to top-center.

    If you want to remove the popup, perform a .remove(...popup-element) on the stackpane.


    Maybe it's not the best way.. but it works!
  • 2. Re: Positioning the Popup control on the Stage (Notification control)
    James_D Guru
    Currently Being Moderated
    I think the problem is that the x and y you're computing from the owner window are coordinates of the content relative to the window; whereas the x and y you are computing to pass into setX(...) and setY(...) are screen coordinates.

    How about this? The idea is to compute the (screen) x coordinates of the notification from the (screen) x coordinates of the window, the width of the window, and the width of the Notification itself (similarly for y). As I'm sure you've figured out, the width of the Notification isn't computed until after it's shown, so I've used some bindings and listeners to keep everything in sync. This centers the Notification, which is not quite what you asked for in terms of y coordinates, but you can adjust as necessary.

    I'm not quite sure what happens if one of the overloaded forms of the show() methods is called; you may want to override those as well to call into this method.
        @Override
        public void show(final Window window) {
          final DoubleBinding xBinding = new DoubleBinding() {
            { super.bind(window.xProperty(), window.widthProperty(), widthProperty()); }
            @Override
            protected double computeValue() {
              return window.getX() + (window.getWidth() - getWidth())/2 ;
            }
          };
          final DoubleBinding yBinding = new DoubleBinding() {
            { super.bind(window.yProperty(), window.heightProperty(), heightProperty()); }
            @Override
            protected double computeValue() {
              return window.getY() + (window.getHeight() - getHeight())/2 ;
            }
          };
          final ChangeListener<Number> xUpdateListener = new ChangeListener<Number>() {
            @Override
            public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
              setX(xBinding.get());
            }
          };
          xBinding.addListener(xUpdateListener);
          final ChangeListener<Number> yUpdateListener = new ChangeListener<Number>() {
            @Override
            public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
              setY(yBinding.get());
            }
          };
          yBinding.addListener(yUpdateListener);
          this.addEventHandler(WindowEvent.WINDOW_HIDDEN, new EventHandler<WindowEvent>() {
            @Override
            public void handle(WindowEvent event) {
              xBinding.removeListener(xUpdateListener);
              yBinding.removeListener(yUpdateListener);
            }
          });
          super.show(window);
        }

Legend

  • Correct Answers - 10 points
  • Helpful Answers - 5 points