Cannot config a button press listener outside the initialize method of Bindable

classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Cannot config a button press listener outside the initialize method of Bindable

ninjathehunter
Hi

I am writing a GUI app using Pivot.

I have a panel that looks like:

public class MyPanel extends BoxPane implements Bindable {
    @BXML private PushButton myButton = null;

    @Override
    public void initialize(final Map<String, Object> namespace, URL location, Resources resources) {
    }

    public PushButton getMyButton() {
        return myButton;
    }
}

I have another class which does this:

public class MyPanelController {
    private MyPanel myPanel;
    private Window myWindow;

    public MyPanelController(MyPanel myPanel, Window myWindow) {
        this.myPanel = myPanel;
        this.myWindow = myWindow;
        initListeners();
    }

    private void initListeners() {
        PushButton myButton = view.getMyButton();
        myButton.getButtonPressListeners().add(new ButtonPressListener(){
            @Override
            public void buttonPressed(Button button) {
                Alert.alert(MessageType.INFO, "Button Clicked!!!", view.getFrame());
            }
        });
    }
}

With this code, when the button is clicked, the press listner code is not executed.

However, if I put the same event listner configuration to the initialize method inside MyPanel, it works:

public class MyPanel extends BoxPane implements Bindable {
    @BXML private PushButton myButton = null;

    @Override
    public void initialize(final Map<String, Object> namespace, URL location, Resources resources) {
        myButton.getButtonPressListeners().add(new ButtonPressListener(){
            @Override
            public void buttonPressed(Button button) {
                Alert.alert(MessageType.INFO, "Button Clicked!!!", view.getFrame());
            }
        });
    }

    public PushButton getMyButton() {
        return myButton;
    }
}

My question is whether the listner handling configuration must be inside the initialize block for it to work??

Thank you very much.
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Cannot config a button press listener outside the initialize method of Bindable

Roger and Beth Whitcomb
Hi, welcome to Pivot!

The short answer is, no the "initListeners" code doesn't have to be
called directly from "initialize" -- it just has to be called from
"somewhere" before the button is pressed.

 From your code it is not clear when/how the "MyPanelController"
constructor would be called.  If it is ever called (from somewhere) then
it would work.  But, my guess would be that you don't ever instantiate
the "MyPanelController" class, or else it only gets instantiated at some
point after the button is pressed.  So, perhaps you could share a bit
more of your code so we can understand better.

HTH,
~Roger

On 8/2/14 12:52 PM, ninjathehunter wrote:

> Hi
>
> I am writing a GUI app using Pivot.
>
> I have a panel that looks like:
>
> public class MyPanel extends BoxPane implements Bindable {
>      @BXML private PushButton myButton = null;
>
>      @Override
>      public void initialize(final Map<String, Object> namespace, URL
> location, Resources resources) {
>      }
>
>      public PushButton getMyButton() {
>          return myButton;
>      }
> }
>
> I have another class which does this:
>
> public class MyPanelController {
>      private MyPanel myPanel;
>      private Window myWindow;
>
>      public MyPanelController(MyPanel myPanel, Window myWindow) {
>          this.myPanel = myPanel;
>          this.myWindow = myWindow;
>          initListeners();
>      }
>
>      private void initListeners() {
>          PushButton myButton = view.getMyButton();
>          myButton.getButtonPressListeners().add(new ButtonPressListener(){
>              @Override
>              public void buttonPressed(Button button) {
>                  Alert.alert(MessageType.INFO, "Button Clicked!!!",
> view.getFrame());
>              }
>          });
>      }
> }
>
> With this code, when the button is clicked, the press listner code is not
> executed.
>
> However, if I put the same event listner configuration to the initialize
> method inside MyPanel, it works:
>
> public class MyPanel extends BoxPane implements Bindable {
>      @BXML private PushButton myButton = null;
>
>      @Override
>      public void initialize(final Map<String, Object> namespace, URL
> location, Resources resources) {
>          myButton.getButtonPressListeners().add(new ButtonPressListener(){
>              @Override
>              public void buttonPressed(Button button) {
>                  Alert.alert(MessageType.INFO, "Button Clicked!!!",
> view.getFrame());
>              }
>          });
>      }
>
>      public PushButton getMyButton() {
>          return myButton;
>      }
> }
>
> My question is whether the listner handling configuration must be inside the
> initialize block for it to work??
>
> Thank you very much.
>
>
>
>
> --
> View this message in context: http://apache-pivot-users.399431.n3.nabble.com/Cannot-config-a-button-press-listener-outside-the-initialize-method-of-Bindable-tp4022979.html
> Sent from the Apache Pivot - Users mailing list archive at Nabble.com.
>
>

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Cannot config a button press listener outside the initialize method of Bindable

ninjathehunter
Hi Roger

Many thanks for your reply.

I have just found the cause of this. Basically, I called the readObject twice, one on the frame that contains MyPanel, and one on the MyPanel itself. This created two instances of MyPanel unfortunately. The listener I added is added to the second instance, which is a standalone instance, not attached to the main frame.

(MainFrame) bxmlSerializer.readObject(MainFrame.class, "/gui/MainFrame.bxml"));
(MyPanel) bxmlSerializer.readObject(MyPanel.class, "/gui/MyPanel.bxml"));

I would also like to ask it is possible to get grand-child component of a component (a component that is not a direct child of a component).

For example, in the above example: MainFrame contains MyPanel, MyPanel contains MyButton.

Is it possible to get MyButton directly from the instance of MainFrame?

I tried myFrame.getNamedComponent() method. But it looks like it can only be used to get direct child of a component.

Thank you very much.
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Cannot config a button press listener outside the initialize method of Bindable

Roger and Beth Whitcomb
Glad you found the problem!  Actually, what you are doing would actually
work, if you didn't put your panel into the MainFrame.bxml, but attached
it after reading it.  But, if the two are inseparable, then it is
usually better to read everything in one shot.

True, the "getNamedComponent()" method only searches direct
descendants.  If you know the hierarchy ahead of time, you can just do a
recursive search on the children of your frame, descending into further
children if the child is a "Container".  Someone else a while back
suggested having a recursive version of "getNamedComponent", which has
its merits, also.  But, I think the methods below are actually easier.

What we've done (mostly) in our application is use the @BXML notation,
in combination with "serializer.bind(...)".  If you assign a
"bxml:id=..." in your *.bxml files, and then define a @BXML Component
.... in your Java file and call the "bind" method after doing the
"readObject", then the variables in your Java code will be assigned the
values of the identified components, and you can access them directly.

This tutorial explains this method pretty well:
http://pivot.apache.org/tutorials/stock-tracker.ui.html

There are other ways, as well, to get a referenced to a component loaded
via "bxml", such as getting the component map from the BXMLSerializer
via the "getNamespace()" method and then calling "get(componentName)" on
that map.

HTH,
~Roger

On 8/2/14 2:50 PM, ninjathehunter wrote:

> Hi Roger
>
> Many thanks for your reply.
>
> I have just found the cause of this. Basically, I called the readObject
> twice, one on the frame that contains MyPanel, and one on the MyPanel
> itself. This created two instances of MyPanel unfortunately. The listener I
> added is added to the second instance, which is a standalone instance, not
> attached to the main frame.
>
> (MainFrame) bxmlSerializer.readObject(MainFrame.class,
> "/gui/MainFrame.bxml"));
> (MyPanel) bxmlSerializer.readObject(MyPanel.class, "/gui/MyPanel.bxml"));
>
> I would also like to ask it is possible to get grand-child component of a
> component (a component that is not a direct child of a component).
>
> For example, in the above example: MainFrame contains MyPanel, MyPanel
> contains MyButton.
>
> Is it possible to get MyButton directly from the instance of MainFrame?
>
> I tried myFrame.getNamedComponent() method. But it looks like it can only be
> used to get direct child of a component.
>
> Thank you very much.
>
>
>
>
> --
> View this message in context: http://apache-pivot-users.399431.n3.nabble.com/Cannot-config-a-button-press-listener-outside-the-initialize-method-of-Bindable-tp4022979p4022981.html
> Sent from the Apache Pivot - Users mailing list archive at Nabble.com.
>
>

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Cannot config a button press listener outside the initialize method of Bindable

ninjathehunter
Hi Roger

Thanks for your reply.

As you suggested, my first instinctive solution for the problem that "getNamedComponent()" method only searches direct descendants was to do a recursive search. However, I think this might not be a good practice after a second thought. I think the whole purpose of introducing bxml (or xaml in Windows WPF or similar) is to group UI definition in one place. This avoids the old fashion of "window.add(button)" style UI construction. By using a recursive search means the Java code varies if the UI structure changes.

I used a lot of

<bxml:include src="MyPanel.bxml"/>

style construction in my UI configuration to avoid a big chunky bxml. I created a class (which implements Bindable) for each bxml. Therefore I end up with one MainFrame class, which is the whole UI, and a lot of classes like MyPanel, which forms part of the MainFrame.

When I call

mainFrame = (MainFrame)bxmlSerializer.readObject(MainFrame.class, "/gui/MainFrame.bxml");

It creates an instance of the MainFrame class, as well as all the other classes that forms part of the MainFrame, like MyPanel.

However, once it is created, I found it is hard for me to refer to it. This is because it is created by the framework and the only way I can refer to them is to recursively search from the root components.

Many thanks.
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Cannot config a button press listener outside the initialize method of Bindable

Sandro Martini
Hi all,
maybe we could think at an enhancement, where the getNamedComponent
method searches even in descendants if not found directly in currrent
level ... but maybe using an additional flag that could be raised to
enable/disable this new feature.
This could be good for you ?

Could you create a new jira issue for this, and maybe attach there a
minimal example of the current situation ?

Thanks a lot.

Bye,
Sandro
Loading...