0

Using the stuff I learned while taking a look at this answer, I'd like to implement a custom pane. The primary purpose of this pane, called BackgroundEffectPane, will be to take an Effect and apply it only to the background. This will allow me to implement the translucent background StackPane in the linked answer in a much cleaner way.

So far, I've read through the documentation of Pane and Node. So far I don't see any obvious methods to override to do this as cleanly as possible. The only thing that strikes me as relevant is the getChildren() method in Pane.

Is this the right thing to Override?

Is Pane the right class to Subclass?

TLDR: Trying to create a custom pane, which methods do I override. All I'm trying to do is add effects to the background.

Community
  • 1
  • 1
Parth Mehrotra
  • 2,712
  • 1
  • 23
  • 31

1 Answers1

2

I wouldn't override any methods for this. If you want to create a subclass of StackPane that provides this functionality, just call getChildren().addAll(...) in the constructor:

public class BackgroundEffectPane extends StackPane {

    public BackgroundEffectPane(Node content) {
        getChildren().addAll(createBackground(), freeze(...), content);
    }

    // code refactored from other answer...
}

Of course, now you no longer really need to subclass at all:

public class BackgroundEffectPane {

    private final Node content ;

    private final Parent effectPane ;

    public BackgroundEffectPane(Node content) {
        this.content = content ;
        this.effectPane = new StackPane(createBackground(), freeze(...), content);
    }

    public Parent getEffectPane() {
        return effectPane ;
    }

    // other code...
}

which better encapsulates the class, by not exposing the underlying implementation of the pane with the effect (i.e. the API does not expose that you are using a StackPane).

James_D
  • 201,275
  • 16
  • 291
  • 322
  • In either case, there isn't anything stopping a user form meddling with the inner workings of the "BackgroundEffectPane", right? They can always mess around with the tree I return, either from the Parent, or the constructor. – Parth Mehrotra Nov 11 '16 at 14:19
  • 1
    In the latter case it would require a downcast (essentially a leap of faith), because `Parent` only exposes an unmodifiable list of children, but yes, in general that is true. The second method though would be more flexible in allowing you to change the implementation without breaking other code that used it (you are not committed to always use a `StackPane` in that version). – James_D Nov 11 '16 at 14:22
  • 1
    If you really want to use a subclassing approach, consider subclassing `Region` and overriding `layoutChildren()`, and the `compute Pref/Min/Max Width/Height` methods. – James_D Nov 11 '16 at 14:24
  • This is an interesting option. If I go the subclass route, it's important that my subclass know what it's parent is. I'm having trouble finding documentation on the "lifecycle" of a Node/Pane/Region. Is there any way whatever I create can find out when someone has added it to a parent? Essentially when getParent() is not null? – Parth Mehrotra Nov 12 '16 at 00:17
  • Thank you for your help by the way James_D – Parth Mehrotra Nov 12 '16 at 00:17
  • Do you think adding a listener to [this method](https://docs.oracle.com/javase/8/javafx/api/javafx/scene/Node.html#parentProperty--) is ther right approach? – Parth Mehrotra Nov 12 '16 at 00:46
  • Okay so both, `layoutChildren()`, and `this.parentProperty().addListener(this)` seem to accurately alert me about the state of `getParent()`. Is there any reason I should prefer one over the other? – Parth Mehrotra Nov 12 '16 at 01:07