Adding Action Listeners at Netbeans - netbeans

I have a Jbutton added on a frame automaticaly by netbeans.
I want to add this Actionlistener to a button.
public class MyActionListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(null,"hello");
}
My problem is that when I add this code
jButton2.addActionListener(MyActionListener);
in order to add the listener to the button I get a "non-static variable jButton2 cannot be referenced from a static context" message.
Since jButton2 is automatically created by netbeans as non static, how can overcome this problem and set the actionlistener as I want?

The error lies in that you are sending an object that has never been instantiated. When you add an action listener to any component you need to send an object that implements the ActionListener interface. Is like adding an instance of the listener to the object.
try this:
jButton2.addActionListener(new MyActionListener());
if you want to use an Anonymous implementation then you will do:
jButton2.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
//some code
}
});

An easy way to add a listener is just to right-click on the button from the design view, select
Events -> Action -> actionPerformed
and the code will be auto-generated for you
public void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
// put what you want to happen, here
}

Related

How is a non-static method accessed without an object?

I am new to JavaFX. In my following code, getHBox() is a non-static method is accessed without creating an object.
public class Main extends Application {
public void start(Stage primaryStage) {
//Main m = new Main();
try {
BorderPane rootPane = new BorderPane();
rootPane.setTop(getHBox());
//rootPane.setTop(m.getHBox());
Scene scene = new Scene(rootPane,400,400);
scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
primaryStage.setScene(scene);
primaryStage.show();
} catch(Exception e) {
e.printStackTrace();
}
}
public HBox getHBox()
{
HBox hb = new HBox(15);
hb.getChildren().add(new Button("Press"));
return hb;
}
public static void main(String[] args) {
launch(args);
}
}
Now I have looked at the answers in Stackoverflow. Guys are talking something about class member. How is getHBox() method different from any other method? Please provide some explanation or direct me to an appropriate tutorial.
In my following code, getHBox() is a non-static method is accessed without creating an object.
That is incorrect. As used in the code presented, getHBox() is invoked only by start(), another non-static method. As an instance method itself, start() must be invoked on an object (one instantiated by JavaFX, for instance). The invocation of getHBox() without designating a target object is implicitly directed to the same object, as if it were this.getHBox().
How is getHBox() method different from any other method?
It isn't, not in any relevant sense, nor is any of this specific to JavaFX.

Can EventBus call a separated Presenter (not a nested Presenter) in GWTP?

Ok, here is my problem. I have 2 presenters: FirstPresenter (ex: abc.com#first) & SecondPresenter (ex: abc.com#second). There is a button on SecondPresenter & when user clicks on that button then the FirstPresenter will popup a message.
So, here is what I did, I used eClipse to create an event name MyEvent, the eclipse generated a class MyEvent.java
On the SecondPresenter, I got:
private EventBus eventBus;
#Inject
public SecondPresenter(final EventBus eventBus, final MyView view,
final MyProxy proxy) {
super(eventBus, view, proxy);
this.eventBus=eventBus;
}
#Override
protected void onBind() {
super.onBind();
passMsgButton.addClickHandler(new ClickHandler(){
#Override
public void onClick(ClickEvent event) {
MyEvent myEvent =new MyEvent();
myEvent.setMsg("hello");
SecondPresenter.this.eventBus.fireEvent(myEvent);
}
});
}
On the FirstPresenter, I got:
private final MyHandler myHandler=new MyHandler(){
#Override
public void onMy(
MyEvent event) {
// TODO Auto-generated method stub
Window.alert(event.getMsg());
}};
#Override
protected void onBind() {
super.onBind();
registerHandler(getEventBus().addHandler(MyEvent.getType(), myHandler));
}
If the FirstPresenter is the nested presenter that is embedded inside the SecondPresenter then that above code works fine. But if they are 2 separated Presenters then the above code didn't work.
Why? I checked Google doc & they just say that EventBus can call a Presenter, they didn't say it must be the nested presenter so I assumed that EventBus can call any separated presenter.
I changed private EventBus to public EventBus, but it didn't help.
What am I missing?
EDIT:
I changed my code a bit, it works partially. I am not sure i'm doing right thing since it still has some issues.
Ok, on the FirstPresenter I implements MyHandler & Override onMy method
public class FirstPresenter extends
Presenter<FirstPresenter.MyView, FirstPresenter.MyProxy> implements MyHandler{
private final MyHandler myHandler=new MyHandler(){
#Override
public void onMy(
MyEvent event) {
// TODO Auto-generated method stub
Window.alert(event.getMsg());
}};
#ProxyEvent
#Override
public void onMy(MyEvent event) {
Window.alert(event.getMsg());
getView().getHtmlPanel().add(new Label("test"));
}
#Override
protected void onBind() {
super.onBind();
registerHandler(getEventBus().addHandler(MyEvent.getType(), myHandler));
}
}
When I click the button on SecondPresenter (a page on a 2nd tab of Webbrowser) then I saw the message popup on the 2nd tab (i.e. the browser didn't make the 1st tab on focus), but when I click on the FirstPresenter (a page on 1st tab) I didn't see the Label("test")?
Why it can call the Window.alert but didn't add the Label onto the FirstPresenter?
Also, how can I get the Browser to set focus on the FirstPresenter (i.e. show the the first tab)?
Am I missing something?
The problem is that if you have two top level presenters only one is active at any time.
I guess that the onBind() method of the FirstPresenter hasn't been called and thus the handler hasn't been attached to the Event on the EventBus.
It works with nested presenters because there both Presenters are "active" at the same time.
You have to rely on ProxyEvent to "wake up the FirstPresenter

GWT Null objects in #UiHandler methods

I am using GWT 2.4 with MVP.
Here is my view object:
public class LoginWidget extends Composite implements LoginWidgetView {
interface Binder extends UiBinder<Widget, LoginWidget> {
}
private static final Binder BINDER = GWT.create(Binder.class);
#UiField Anchor settings;
public LoginWidget() {
initWidget(BINDER.createAndBindUi(this));
}
#UiHandler("settings")
void handleSettingsClick(ClickEvent e) {
presenter.showSettings();
}
private Presenter presenter;
#Override
public void setPresenter(Presenter presenter) {
this.presenter = presenter;
}
}
I am setting the view´s presenter by
...
getLoginWidget().setPresenter(new LoginWidgetPresenter(placeController));
LoginWidgetPresenter of course implements the view´s Presenter interface. But when I click on the settings anchor, the presenter reference is still null, so presenter.showSettings() throws a NullPointerException.
I suppose that after calling the LoginWidget´s constructor and initializing the widget by
initWidget(BINDER.createAndBindUi(this));
the click handling code in my #UiHandler("settings") method ignores changes to the used objects like my presenter object??
Is there a way to set the presenter object after calling the initWidget() method?
Or is it possible to customize the #UiHandler/initWidget()-behaviour that I can set my presenter afterwards?
Thanks, Manuel
I implement MVP in another way and UIBinder work for my. Maybe if you pass the LoginWidgetPresenter in LoginWidget constructor it works.
public LoginWidget(Presenter presenter) {
this.presenter = presenter;
initWidget(BINDER.createAndBindUi(this));
}
...
getLoginWidget(new LoginWidgetPresenter(placeController));
There are lot of things, which could have gone wrong. The easiest thing is to try to debug your code, by putting breakpoints handleSettings and 'setPresenter' methods.
My guess is that one of following is happening:
setPresenter is never actually called
or
getLoginWidget() always returns a new instance of the widget, and it is quite possible that you are setting presenter on one instance of login widget, but displaying totally different instance of the widget
or
You have getLoginWidget().setPresenter(null) somewhere in your code
or any other guess. It is much more easier to debug, and see for yourself, where and how presenter instance is passed. Anyway, UiBinder will not erase your field values (unless it is modified by someone else to make fun of you)

How to expose events from child objects on the containing composite object?

I have a composite widget that contains many buttons (eg. Button1, Button2, etc). I can't figure how to expose button click events on the composite widget. I'm trying to avoid creating custom events such as Button1ClickEvent and Button2ClickEvent and instead reuse the existing GWT ClickEvent for both of them. The following code snippet can give an idea what I'm trying to do:
public class WidgetWithTwoButtons extends Composite {
...
#UiField Button button1;
#UiField Button button2;
#UiHandler("button1")
void onButton1Click(ClickEvent event) {
// TODO fire click event on Button1ClickHandler
}
public HandlerRegistration addButton1ClickHandler(ClickHandler handler) {
return addDomHandler(handler, ClickEvent.getType());
}
#UiHandler("button2")
void onButton1Click(ClickEvent event) {
// TODO fire click event on Button2ClickHandler
}
public HandlerRegistration addButton2ClickHandler(ClickHandler handler) {
return addDomHandler(handler, ClickEvent.getType());
}
}
I think this is not the best practice. I'd appreciate if you give pointers to recommended solutions/examples to this problem in your answers. Thanks!
I started thinking about your problem and first noticed instead of using addDomHandler you can change your current addButton1ClickHandler(ClickHandler handler) simply to :
public HandlerRegistration addButton1ClickHandler(ClickHandler handler) {
return button1.addClickHandler(handler);
}
If you had only one button, you could expose it by making your Composite implement HasClickHandlers and implement the below method to pass it through to your button:
#Override
public HandlerRegistration addClickHandler(ClickHandler handler) {
return button1.addClickHandler(handler);
}
But since you have many buttons, you need a method that takes the button you want to add your clickHandler to as a parameter such as :
public HandlerRegistration addClickHandlerToButton(ClickHandler handler, Button target){
return target.addClickHandler(handler);
}
The problem with this approach is, to use this you need to have a reference to your buttons which means you need to define getter methods for your buttons in your composite such as public Button getButton1() . When you expose your buttons like this, the problem is one does not need a passthrough method on the composite anymore since he/she can directly access buttons anyway making the above approach that takes a target button as parameter obsolete. Worst part is he/she can even change the styles and even detach those buttons.
To solve this you can expose your buttons over the HasClickHandlers interface.
So IMHO this is how i beleive it should be done:
public class ComplexComposite extends Composite {
private Button button1 = new Button("btn1");
private Button button2 = new Button("btn2");
public ComplexComposite(){
HorizontalPanel panel = new HorizontalPanel();
panel.add(button1);
panel.add(button2);
initWidget(panel);
}
public HasClickHandlers getButton1(){
return button1;
}
public HasClickHandlers getButton2(){
return button2;
}
}
With this approach you expose your buttons only over the desired interface and one can add
click handlers such as :
ComplexComposite composite = new ComplexComposite();
composite.getButton1().addClickHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
...
}
});

GWT: how to fire custom events from View and consumed by Activity

I can't make a custom event be received in the Activity. Can anyone please tell me what am I missing? I am using GWT 2.1, MVP pattern and UiBinder.
Here's a sample of what I wrote:
Let's say I have MyCustomEvent class and its handler interface MyCustomEventHandler with its onMyCustomEvent(MyCustomEvent event) method.
I implement the handler interface in the Activity:
class MyActivity extends AbstractActivity implements MyCustomEventHandler {
....
public void onMyCustomEvent(MyCustomEvent event) {
doWhatYouKnow();
}
//EventBus is injected with GIN
public void start(AcceptsOneWidget container, EventBus eventBus) {
...
eventBus.addHandler(MyEvent.TYPE, this);
}
}
Now, the sending part in the view:
public class MyWidget extends Composite {
final PopUpPanel myPopUp;
public MyWidget() {
initWidget(uiBinder.createAndBindUi(this));
myPopUp.addCloseHandler(new CloseHandler<PopupPanel>() {
#Override
public void onClose(CloseEvent<PopupPanel> event) {
MyEvent event = new MyEvent();
fireEvent(event);
}
});
}
}
No exception are thrown and unfortunately onMyCustomEvent is never called in the MyActivity class. Any idea? Thanks a million.
#MyWidget
you can make the constructor take parameter ( eventBus )
which you can pass this from class MyActivity
so when you fire the event #MyActivity
the action will be executed #MyWidget
try this , i think it will work .
I think one of your comments is pointing you in the right direction here. What I'm going to guess is going on is that you have more than one EventBus floating around (there should usually only be one event bus per application).
First of all, make sure the EventBus in your Gin module is bound in the Singleton scope. Also, make sure this is the event bus that you pass in to your PlaceController, and not one you're constructing on your own.
Also, I wouldn't be too worried about the fact that your object is a ResettableEventBus in one place. I believe that's just an object that's created by the Activities/Places framework that just wraps the EventBus object you give it.