SpanButton client property throws NullPointerException - codenameone

I am trying to get the client property on a SpanButton when clicked. It is throwing a NullPointerException.
I tested the same code with a regular button and it works just fine. I believe there could be a bug there.
Here is how you can recreate this issue from a barebone project:
Form hi = new Form("Hi World");
Button button = new Button("Button");
button.putClientProperty("id", 100);
SpanButton spanButton = new SpanButton("SpanButton");
spanButton.putClientProperty("id", 200);
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent evt) {
int id = (int) evt.getComponent().getClientProperty("id");
System.out.println("Standard Button action listener: id = " + id);
}
});
spanButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent evt) {
int id = (int) evt.getComponent().getClientProperty("id");
System.out.println("Span button action listener: id = " + id);
}
});
hi.addComponent(button);
hi.addComponent(spanButton);
hi.show();
If you click on the button, the output is printed correctly:
Standard Button action listener: id = 100
If you click on the SpanButton, a NullPointerException is thrown. Upon investigation, I found out that the SpanButton getClientProperty("id") is returning null.
Note: I need to use the SpanButton because of its variable size support.

Instead of getComponent() use the aptly named getActualComponent().
The JavaDocs explain why:
Identical to ActionEvent#getComponent() except for the fact that a lead component will be returned if such a lead component is available.
This is important for components such as MultiButton which will return the underlying button instead.

Related

CodenameOne Dialog showing without a call to show

I am aware of existing error dialogs but I am trying to create my own dialog from scratch.
public class ExceptionDialog extends Dialog {
private Button okButton;
private SpanLabel errorMessage;
private Label title;
public ExceptionDialog(String titleText, String messageText, String buttonText) {
super();
this.setLayout(new BorderLayout());
okButton = new Button(buttonText);
errorMessage = new SpanLabel(messageText);
title = new Label(titleText);
this.add(BorderLayout.NORTH, title);
this.add(BorderLayout.CENTER_BEHAVIOR_CENTER, errorMessage);
this.add(BorderLayout.SOUTH, okButton);
this.setAutoDispose(false);
this.setDisposeWhenPointerOutOfBounds(true);
this.showStretched(BorderLayout.SOUTH, true);
this.setTransitionInAnimator(CommonTransitions.createSlide(CommonTransitions.SLIDE_VERTICAL, true, 1000));
this.setTransitionOutAnimator(CommonTransitions.createSlide(CommonTransitions.SLIDE_VERTICAL, false, 1000));
Dialog thisDialog = this;
okButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ev) {
System.out.println("BUTTON CLICKE");
thisDialog.dispose();
}
});
}
}
The problem: I noticed that on initialization, the dialog is showing without really calling ex.show(). Also, the button does not work, the only way to get the dialog to disappear is by clicking somewhere else on the screen.
Form hi = new Form("Hi World", BoxLayout.y());
hi.add(new Label("Hi World"));
hi.show();
ExceptionDialog ex = new ExceptionDialog("A", "B", "C");
Then I tried appending ex.show() to the code above. Now the dialog gets shown twice. The second time with a working button dismissing the dialog.
showStretched is show it will show the dialog and block until the dialog is disposed.

Actionlistener in the command of the side menu opens blank form but the same in the button action listener opens the form normally

I have called a form name Groups from button action listener and command action listener. In both, I have called a connection request. In postResponse method of
the connection showForm is declared. The issue here is that it works great when I click the button and the groups form opens normally but when I click the command from the hamburger menu, the blank form is shown but as soon as the screen is touched, the contents are displayed (both in real devices and simulator). PS I have also called revalidate method in Groups form. How can it work in one and not in other because I have same code in both command & button actionListener
Command in the side menu
Command goToGroup = new Command("Tables",homeIcon1) {
#Override
public void actionPerformed(ActionEvent evt) {
connectionGroup = new GroupConnection();
connectionGroup.groupConnection(StateMachine.this);
}
};
f.addCommand(goToGroup);
button action listener in a form
groups.addActionListener((e) -> {
connectionGroup = new GroupConnection();
connectionGroup.groupConnection(this);
});
Connection
public class GroupConnection {
void groupConnection(StateMachine sm) {
ConnectionRequest connectionRequest = new ConnectionRequest() {
#Override
protected void readResponse(InputStream input) throws IOException {
- - - - - -
- - - - - -
}
#Override
protected void postResponse() {
sm.showForm("Groups", null);
}
- - - - - -
- - - - - -
};
}
}
groups form:
protected void beforeGroups(Form f) {
Display.getInstance().scheduleBackgroundTask(() -> {
Display.getInstance().callSerially(() -> {
if (connectionGroup.responses != null) {
for (Map<String, Object> element : connectionGroup.responses) {
String id = (String) element.get("id");
String tableName = (String) element.get("name");
String tableImg = (String) element.get("tablelogo");
- - - - - - - -
- - - -- - - - - -
}
}
});
f.revalidate();
});
}
The main difference between the two is that the side menu navigates to a temporary form and then reshows the form after. I'm guessing your call to revalidate() was made at the wrong time when the form hasn't been shown/constructed yet.

Handle event for html button codename one

In form I embedded WebBrowser component with lots of html contents (Mainly Table, buttons ) for rich ui. Is it possible to handle event on clicking html button ?
Sure, look at the kitchen sink demo for a sample.
Generally just navigate to a URL on the event and implement your own BrowserNavigationCallback to handle navigation to that specific URL.
This is the code from the Kitchen Sink demo notice the setBrowserNavigationCallback block:
final WebBrowser wb = new WebBrowser();
if(wb.getInternal() instanceof BrowserComponent) {
Button btn = new Button("Add");
final TextArea content = new TextArea();
Container north = new Container(new BorderLayout());
north.addComponent(BorderLayout.CENTER, content);
north.addComponent(BorderLayout.EAST, btn);
cnt.addComponent(BorderLayout.NORTH, north);
content.setHint("Add to web document");
btn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
((BrowserComponent)wb.getInternal()).execute("fnc('" + content.getText() + "');");
}
});
((BrowserComponent)wb.getInternal()).setBrowserNavigationCallback(new BrowserNavigationCallback() {
public boolean shouldNavigate(String url) {
if(url.startsWith("http://sayhello")) {
// warning!!! This is not on the EDT and this method MUST return immediately!
Display.getInstance().callSerially(new Runnable() {
public void run() {
((BrowserComponent)wb.getInternal()).execute("fnc('this was written by Java code!')");
}
});
return false;
}
return true;
}
});
}

codenameone reference components from another function

I have created a register form (not using the designer).
On the form I have created numerous text fields as well as a button with ...
Button btnRegister = new Button();
btnRegister.setName("btnRegister");
btnRegister.setText("Register");
btnRegister.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
frmRegister_btnRegister(f);
}
});
f.addComponent(btnRegister);
My question is how do I reference the textfields in the function being called from the button action listener. Specifically I am trying to set up arguments to use for a network call using addArgument. When I used the designer I used find(ComponentName) but that is not available anymore.
private void frmRegister_btnRegister(Form f) {
// register new user
ConnectionRequest r = new ConnectionRequest();
r.setUrl(sUrlWebSvc);
r.setPost(true);
r.addArgument("Rest", "1"); // restaurant code
r.addArgument("Req", "Register"); // R = register
//r.addArgument("first_name", findTxtUsertName(c).getText());
// show spinning dialog while connecting
InfiniteProgress prog = new InfiniteProgress();
Dialog dlg = prog.showInifiniteBlocking();
r.setDisposeOnCompletion(dlg);
NetworkManager.getInstance().addToQueueAndWait(r);
//System.out.println(r.getResponseData());
}
Assuming its defined just above this line:
Button btnRegister = new Button();
As:
TextField txt =....
Just change it to:
final TextField txt =....
And then you can pass it (or its getText() string value) to:
btnRegister.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
frmRegister_btnRegister(f, txt);
}
});
Naturally you will need to update the signature of frmRegister_btnRegister to accept a text field or a string.

how to display a image on click of a button using LWUIT

I am trying to write a application using LWUIT where I want a image to be displayed on click of a button.
I have the following code. But I get an exception if the button is clicked twice.
Please help me display the image without giving any exception.
final Form f = new Form("Static TAF");
Button TrackMe = new Button("TrackMe");
Image TrackMeicon = null;
TrackMeicon = Image.createImage("/hello/follow.jpeg");
final Label TrackMeLabel = new Label(TrackMeicon);
TrackMe.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent ae)
{
System.out.println("Removing the previous Images");
f.addComponent(TrackMeLabel);
}
});
Please Help
When you are clicking the button for the first time, image is added to the form. When you are clicking for the second time, that image already exists in the form. So, it will throw "Component already exists" exception.
Your action listener should be
TrackMe.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent ae) {
System.out.println("Removing the previous Images");
f.removeComponent(TrackMeLabel);
f.addComponent(TrackMeLabel);
}
});
TrackMe.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent ae) {
System.out.println("Removing the previous Images");
final Label TrackMeLabel = new Label(TrackMeicon);
f.removeAll();
f.addComponent(TrackMeLabel);
}
});
If you want yo add only one image you can use this:
....
TrackMe.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent ae) {
if(!f.containes(TrackMeLabel))
f.addComponent(TrackMeLabel);
}
if you want some imges you need something like that:
....
TrackMe.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent ae) {
Image TrackMeicon = null;
TrackMeicon = Image.createImage("/hello/follow.jpeg");
Label TrackMeLabel = new Label(TrackMeicon);
f.addComponent(TrackMeLabel);
}

Resources