I'm trying to make my code neater by using multiple classes for my applications
form options. Currently I keep getting null pointer exceptions when trying to setCurrent.
Here is my main class the error starts in my command listener when I call the other class.
import java.util.*;
import javax.microedition.lcdui.*;
import javax.microedition.midlet.MIDlet;
public class CalFrontEnd extends MIDlet implements CommandListener {
private Display display;
private List list = new List("Please Select a Option", List.IMPLICIT);
private List Blist = new List("Please Select a Browsing Option", List.IMPLICIT);
private Command select = new Command("Select", Command.SCREEN, 1);
private Command exit = new Command("Exit", Command.EXIT, 2);
private Command save = new Command("Save,", Command.SCREEN, 2);
private DateField calendar;
Alert alert;
//
//
//
public CalFrontEnd() {
display = Display.getDisplay(this);
list.append("Select Date", null);
list.append("Add Events", null);
list.append("Remove Events", null);
list.append("Browse Events", null);
list.addCommand(select);
list.addCommand(exit);
list.setCommandListener(this);
}
//
//Start Application Method
//
public void startApp() {
display.setCurrent(list);
}
//
//Pause Application Method
//
public void pauseApp() {
}
//
//Destroy Application Method
//
public void destroyApp(boolean unconditional) {
}
//
//Method creates form which contains calendar
//
/*public void selectDate()
{
calendar = new DateField("Date In :", DateField.DATE, TimeZone.getTimeZone("GMT"));
Form cform = new Form("Calendar");
cform.append(calendar);
cform.addCommand(exit);
display.setCurrent(cform);
}*/
//
//Method creates form which contains adding events
//
public void AddEvents()
{
TextBox aeText = new TextBox("Add Event","", 256, 0);
display.setCurrent(aeText);
}
//
//Method creates form which contains removing events
//
public void RemoveEvents()
{
Form reform = new Form("Remove Event");
reform.append(calendar);
display.setCurrent(reform);
}
//
//Method creates form which contains removing events
//
public void BrowseEvents()
{
Blist.append("Monthly", null);
Blist.append("Daily", null);
Blist.addCommand(select);
Blist.addCommand(exit);
Blist.setCommandListener(this);
display.setCurrent(Blist);
}
//
//but it's better practice to make each form a different class extending CommandListener and it's own commandAction. And leave the display public static in MIDlet class
//...
public void commandAction(Command command, Displayable displayable) {
if (displayable == list) {
if (command == List.SELECT_COMMAND) {
switch (list.getSelectedIndex()) {
case 0: // select date
SelectDate.BuildCalendar(); //Error Here
break;
case 1: //add events
AddEvents();
break;
}
} else if (command == exit) {
destroyApp(false);
notifyDestroyed();
}
}
}
}
And here is the class that is being called.
public class SelectDate
{
private static DateField calendar;
private static Form form = new Form("derb");
private static Command select = new Command("Select", Command.SCREEN, 1);
private static Command exit = new Command("Exit", Command.EXIT, 2);
private static Command save = new Command("Save,", Command.SCREEN, 2);
private static Display display;
public static void BuildCalendar()
{
calendar = new DateField("Date In :", DateField.DATE, TimeZone.getTimeZone("GMT"));
form.append(calendar);
form.addCommand(exit);
display.setCurrent(form);
}
}
The NullPointerException happens because display in SelectDate class is null.
To fix that, you can for example drop it from there and instead, add to method parameters:
// ...
public static void BuildCalendar(Display display) // added parameter
Then, when you invoke above method from CalFrontEnd, pass the instance of display there:
// ...
SelectDate.BuildCalendar(display); //Error will go away
Related
I'm developping an application, and now, I don't know what to do next:
I have a list of elements, each element has some informations + an ID + a logo.
What I want to do is creating a list like in the picture
List
Of course, I want it in a single layer, with the logo, some informations, and a button to define an action; where I could use the ID of the selected item.
I did some research, may be I found some relative subjects, but none of what I want.
My list is a
ArrayList<ArrayList<String>>
filled by data from database.
Thank you
Here it is:
public class Avancee extends Activity {
// Log tag
private static final String TAG = MainActivity2.class.getSimpleName();
// Movies json url
private static final String url = "http://blabla.com/movie.json";
private ProgressDialog pDialog;
private List<Movie> movieList = new ArrayList<Movie>();
private ListView listView;
private CustomListAdapter adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listView = (ListView) findViewById(R.id.list);
adapter = new CustomListAdapter(this, movieList);
listView.setAdapter(adapter);
pDialog = new ProgressDialog(this);
// Showing progress dialog before making http request
pDialog.setMessage("Loading...");
pDialog.show();
// changing action bar color
getActionBar().setBackgroundDrawable(
new ColorDrawable(Color.parseColor("#1b1b1b")));
// Creating volley request obj
JsonArrayRequest movieReq = new JsonArrayRequest(url,
new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
//Log.d(TAG, response.toString());
hidePDialog();
String result = getIntent().getStringExtra("ITEM_EXTRAA");
System.out.println(result);
try{
JSONArray ja = new JSONArray(result);
for (int i = 0; i < ja.length(); i++) {
try {
JSONObject obj = ja.getJSONObject(i);
Movie movie = new Movie();
movie.setTitle(obj.getString("title"));
movie.setLocation(obj.getString("location_search_text"));
movie.setId(obj.getInt("id"));
// adding movie to movies array
movieList.add(movie);
} catch (JSONException e) {
e.printStackTrace();
}
}
}catch(JSONException e){
Log.e("log_tag", "Error parsing data "+e.toString());
}
// notifying list adapter about data changes
// so that it renders the list view with updated data
adapter.notifyDataSetChanged();
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
VolleyLog.d(TAG, "Error: " + error.getMessage());
hidePDialog();
}
});
// Adding request to request queue
AppController.getInstance().addToRequestQueue(movieReq);
}
#Override
public void onDestroy() {
super.onDestroy();
hidePDialog();
}
private void hidePDialog() {
if (pDialog != null) {
pDialog.dismiss();
pDialog = null;
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
It's the "id" that I want to get in the OnClick event.
use this code
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int position, long l) {
Movie movie= movieList.get(position);
}
});
//here position will give you the id of listview cell so you can use it like
Movie movie= movieList.get(position);
then you can use it get all the data inside your moview object
i have a view pager with 3 fragment one of the fragment
have searchview widget and i get to know that i can,t implement the standard search interface so i implement some thing like this but how to implement Custom Suggestions in SearchView
public class LoaderCursor extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
FragmentManager fm = getFragmentManager();
// Create the list fragment and add it as our sole content.
if (fm.findFragmentById(android.R.id.content) == null) {
CursorLoaderListFragment list = new CursorLoaderListFragment();
fm.beginTransaction().add(android.R.id.content, list).commit();
}
}
public static class CursorLoaderListFragment extends ListFragment
implements OnQueryTextListener, LoaderManager.LoaderCallbacks<Cursor> {
// This is the Adapter being used to display the list's data.
SimpleCursorAdapter mAdapter;
// If non-null, this is the current filter the user has provided.
String mCurFilter;
#Override public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
// Give some text to display if there is no data. In a real
// application this would come from a resource.
setEmptyText("No phone numbers");
// We have a menu item to show in action bar.
setHasOptionsMenu(true);
// Create an empty adapter we will use to display the loaded data.
mAdapter = new SimpleCursorAdapter(getActivity(),
android.R.layout.simple_list_item_2, null,
new String[] { Contacts.DISPLAY_NAME, Contacts.CONTACT_STATUS },
new int[] { android.R.id.text1, android.R.id.text2 }, 0);
setListAdapter(mAdapter);
// Start out with a progress indicator.
setListShown(false);
// Prepare the loader. Either re-connect with an existing one,
// or start a new one.
getLoaderManager().initLoader(0, null, this);
}
#Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
// Place an action bar item for searching.
MenuItem item = menu.add("Search");
item.setIcon(android.R.drawable.ic_menu_search);
item.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
SearchView sv = new SearchView(getActivity());
sv.setOnQueryTextListener(this);
item.setActionView(sv);
}
public boolean onQueryTextChange(String newText) {
// Called when the action bar search text has changed. Update
// the search filter, and restart the loader to do a new query
// with this filter.
mCurFilter = !TextUtils.isEmpty(newText) ? newText : null;
getLoaderManager().restartLoader(0, null, this);
return true;
}
#Override public boolean onQueryTextSubmit(String query) {
// Don't care about this.
return true;
}
#Override public void onListItemClick(ListView l, View v, int position, long id) {
// Insert desired behavior here.
Log.i("FragmentComplexList", "Item clicked: " + id);
}
// These are the Contacts rows that we will retrieve.
static final String[] CONTACTS_SUMMARY_PROJECTION = new String[] {
Contacts._ID,
Contacts.DISPLAY_NAME,
Contacts.CONTACT_STATUS,
Contacts.CONTACT_PRESENCE,
Contacts.PHOTO_ID,
Contacts.LOOKUP_KEY,
};
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
// This is called when a new Loader needs to be created. This
// sample only has one Loader, so we don't care about the ID.
// First, pick the base URI to use depending on whether we are
// currently filtering.
Uri baseUri;
if (mCurFilter != null) {
baseUri = Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI,
Uri.encode(mCurFilter));
} else {
baseUri = Contacts.CONTENT_URI;
}
// Now create and return a CursorLoader that will take care of
// creating a Cursor for the data being displayed.
String select = "((" + Contacts.DISPLAY_NAME + " NOTNULL) AND ("
+ Contacts.HAS_PHONE_NUMBER + "=1) AND ("
+ Contacts.DISPLAY_NAME + " != '' ))";
return new CursorLoader(getActivity(), baseUri,
CONTACTS_SUMMARY_PROJECTION, select, null,
Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC");
}
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
// Swap the new cursor in. (The framework will take care of closing the
// old cursor once we return.)
mAdapter.swapCursor(data);
// The list should now be shown.
if (isResumed()) {
setListShown(true);
} else {
setListShownNoAnimation(true);
}
}
public void onLoaderReset(Loader<Cursor> loader) {
// This is called when the last Cursor provided to onLoadFinished()
// above is about to be closed. We need to make sure we are no
// longer using it.
mAdapter.swapCursor(null);
}
}
}
I'm creating a TableView to show information regarding a list of custom objects (EntityEvents).
The table view must have 2 columns.
First column to show the corresponding EntityEvent's name.
The second column would display a button. The button text deppends on a property of the EntityEvent. If the property is ZERO, it would be "Create", otherwise "Edit".
I managed to do it all just fine, except that I can't find a way to update the TableView line when the corresponding EntityEvent object is changed.
Very Important: I can't change the EntityEvent class to use JavaFX properties, since they are not under my control. This class uses PropertyChangeSupport to notify listeners when the monitored property is changed.
Note:
I realize that adding new elements to the List would PROBABLY cause the TableView to repaint itself, but that is not what I need. I say PROBABLY because I've read about some bugs that affect this behavior.
I tried using this approach to force the repaint, by I couldn't make it work.
Does anyone knows how to do it?
Thanks very much.
Here is a reduced code example that illustrates the scenario:
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import javafx.application.Application;
import javafx.beans.property.ReadOnlyStringWrapper;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ContentDisplay;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableColumn.CellDataFeatures;
import javafx.scene.control.TableView;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javafx.util.Callback;
public class Main extends Application {
//=============================================================================================
public class EntityEvent {
private String m_Name;
private PropertyChangeSupport m_NamePCS = new PropertyChangeSupport(this);
private int m_ActionCounter;
private PropertyChangeSupport m_ActionCounterPCS = new PropertyChangeSupport(this);
public EntityEvent(String name, int actionCounter) {
m_Name = name;
m_ActionCounter = actionCounter;
}
public String getName() {
return m_Name;
}
public void setName(String name) {
String lastName = m_Name;
m_Name = name;
System.out.println("Name changed: " + lastName + " -> " + m_Name);
m_NamePCS.firePropertyChange("Name", lastName, m_Name);
}
public void addNameChangeListener(PropertyChangeListener listener) {
m_NamePCS.addPropertyChangeListener(listener);
}
public int getActionCounter() {
return m_ActionCounter;
}
public void setActionCounter(int actionCounter) {
int lastActionCounter = m_ActionCounter;
m_ActionCounter = actionCounter;
System.out.println(m_Name + ": ActionCounter changed: " + lastActionCounter + " -> " + m_ActionCounter);
m_ActionCounterPCS.firePropertyChange("ActionCounter", lastActionCounter, m_ActionCounter);
}
public void addActionCounterChangeListener(PropertyChangeListener listener) {
m_ActionCounterPCS.addPropertyChangeListener(listener);
}
}
//=============================================================================================
private class AddPersonCell extends TableCell<EntityEvent, String> {
Button m_Button = new Button("Undefined");
StackPane m_Padded = new StackPane();
AddPersonCell(final TableView<EntityEvent> table) {
m_Padded.setPadding(new Insets(3));
m_Padded.getChildren().add(m_Button);
m_Button.setOnAction(new EventHandler<ActionEvent>() {
#Override public void handle(ActionEvent actionEvent) {
// Do something
}
});
}
#Override protected void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (!empty) {
setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
setGraphic(m_Padded);
m_Button.setText(item);
}
}
}
//=============================================================================================
private ObservableList<EntityEvent> m_EventList;
//=============================================================================================
#SuppressWarnings("unchecked")
#Override
public void start(Stage primaryStage) {
primaryStage.setTitle("Table View test.");
VBox container = new VBox();
m_EventList = FXCollections.observableArrayList(
new EntityEvent("Event 1", -1),
new EntityEvent("Event 2", 0),
new EntityEvent("Event 3", 1)
);
final TableView<EntityEvent> table = new TableView<EntityEvent>();
table.setItems(m_EventList);
TableColumn<EntityEvent, String> eventsColumn = new TableColumn<>("Events");
TableColumn<EntityEvent, String> actionCol = new TableColumn<>("Actions");
actionCol.setSortable(false);
eventsColumn.setCellValueFactory(new Callback<CellDataFeatures<EntityEvent, String>, ObservableValue<String>>() {
public ObservableValue<String> call(CellDataFeatures<EntityEvent, String> p) {
EntityEvent event = p.getValue();
event.addActionCounterChangeListener(new PropertyChangeListener() {
#Override
public void propertyChange(PropertyChangeEvent event) {
// TODO: I'd like to update the table cell information.
}
});
return new ReadOnlyStringWrapper(event.getName());
}
});
actionCol.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<EntityEvent, String>, ObservableValue<String>>() {
#Override
public ObservableValue<String> call(TableColumn.CellDataFeatures<EntityEvent, String> ev) {
String text = "NONE";
if(ev.getValue() != null) {
text = (ev.getValue().getActionCounter() != 0) ? "Edit" : "Create";
}
return new ReadOnlyStringWrapper(text);
}
});
// create a cell value factory with an add button for each row in the table.
actionCol.setCellFactory(new Callback<TableColumn<EntityEvent, String>, TableCell<EntityEvent, String>>() {
#Override
public TableCell<EntityEvent, String> call(TableColumn<EntityEvent, String> personBooleanTableColumn) {
return new AddPersonCell(table);
}
});
table.getColumns().setAll(eventsColumn, actionCol);
table.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
// Add Resources Button
Button btnInc = new Button("+");
btnInc.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent ev) {
System.out.println("+ clicked.");
EntityEvent entityEvent = table.getSelectionModel().getSelectedItem();
if (entityEvent == null) {
System.out.println("No Event selected.");
return;
}
entityEvent.setActionCounter(entityEvent.getActionCounter() + 1);
// TODO: I expected the TableView to be updated since I modified the object.
}
});
// Add Resources Button
Button btnDec = new Button("-");
btnDec.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent ev) {
System.out.println("- clicked.");
EntityEvent entityEvent = table.getSelectionModel().getSelectedItem();
if (entityEvent == null) {
System.out.println("No Event selected.");
return;
}
entityEvent.setActionCounter(entityEvent.getActionCounter() - 1);
// TODO: I expected the TableView to be updated since I modified the object.
}
});
container.getChildren().add(table);
container.getChildren().add(btnInc);
container.getChildren().add(btnDec);
Scene scene = new Scene(container, 300, 600, Color.WHITE);
primaryStage.setScene(scene);
primaryStage.show();
}
//=============================================================================================
public Main() {
}
//=============================================================================================
public static void main(String[] args) {
launch(Main.class, args);
}
}
Try the javafx.beans.property.adapter classes, particularly JavaBeanStringProperty and JavaBeanIntegerProperty. I haven't used these, but I think you can do something like
TableColumn<EntityEvent, Integer> actionCol = new TableColumn<>("Actions");
actionCol.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<EntityEvent, Integer> ev) {
return new JavaBeanIntegerPropertyBuilder().bean(ev.getValue()).name("actionCounter").build();
});
// ...
public class AddPersonCell extends TableCell<EntityEvent, Integer>() {
final Button button = new Button();
public AddPersonCell() {
setPadding(new Insets(3));
setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
button.setOnAction(...);
}
#Override
public void updateItem(Integer actionCounter, boolean empty) {
if (empty) {
setGraphic(null);
} else {
if (actionCounter.intValue()==0) {
button.setText("Create");
} else {
button.setText("Add");
}
setGraphic(button);
}
}
}
As I said, I haven't used the Java bean property adapter classes, but the idea is that they "translate" property change events to JavaFX change events. I just typed this in here without testing, but it should at least give you something to start with.
UPDATE: After a little experimenting, I don't think this approach will work if your EntityEvent is really set up the way you showed it in your code example. The standard Java beans bound properties pattern (which the JavaFX property adapters rely on) has a single property change listener and an addPropertyChangeListener(...) method. (The listeners can query the event to see which property changed.)
I think if you do
public class EntityEvent {
private String m_Name;
private PropertyChangeSupport pcs = new PropertyChangeSupport(this);
private int m_ActionCounter;
public EntityEvent(String name, int actionCounter) {
m_Name = name;
m_ActionCounter = actionCounter;
}
public String getName() {
return m_Name;
}
public void setName(String name) {
String lastName = m_Name;
m_Name = name;
System.out.println("Name changed: " + lastName + " -> " + m_Name);
pcs.firePropertyChange("name", lastName, m_Name);
}
public void addPropertyChangeListener(PropertyChangeListener listener) {
pcs.addPropertyChangeListener(listener);
}
public void removePropertyChangeListener(PropertyChangeListener listener) {
pcs.removePropertyChangeListener(listener);
}
public int getActionCounter() {
return m_ActionCounter;
}
public void setActionCounter(int actionCounter) {
int lastActionCounter = m_ActionCounter;
m_ActionCounter = actionCounter;
System.out.println(m_Name + ": ActionCounter changed: " + lastActionCounter + " -> " + m_ActionCounter);
pcs.firePropertyChange("ActionCounter", lastActionCounter, m_ActionCounter);
}
}
it will work with the adapter classes above. Obviously, if you have existing code calling the addActionChangeListener and addNameChangeListener methods you would want to keep those existing methods and the existing property change listeners, but I see no reason you can't have both.
I'm trying to implement Menu with select box which sets to display or not component. I have this checkbox:
final CheckMenuItem toolbarSubMenuNavigation = new CheckMenuItem("Navigation");
toolbarSubMenuNavigation.setOnAction(new EventHandler<ActionEvent>()
{
#Override
public void handle(ActionEvent e)
{
DataTabs.renderTab = toolbarSubMenuNavigation.isSelected();
// call here the getter setter and send boolean flag
System.out.println("subsystem1 #1 Enabled!");
}
});
And I have this tabpane which I want to render only if I have selected the checkbox:
public static boolean renderTab;
public DataTabs()
{
}
public boolean isRenderTab()
{
return renderTab;
}
public void setRenderTab(boolean renderTab)
{
this.renderTab = renderTab;
}
// below this code
tabPane.setVisible(renderTab);
When I run the code it's not working. I also tested this:
DataTabs tabs = new DataTabs(); // instantiate first
tabs.setRenderTab(toolbarSubMenuNavigation.isSelected());
public static boolean renderTab;
TabPane tabPane = new TabPane();
public DataTabs()
{
}
public boolean isRenderTab()
{
return renderTab;
}
public void setRenderTab(boolean renderTab)
{
tabPane.setVisible(renderTab);
}
But again there is no result when I run the code and I check or uncheck the checkbox.
This is the complete source code:
http://pastebin.com/tkj4Fby1
Maybe I need to add listener or something else which I'm missing?
EDIT
Test 3
I also tested this code:
final CheckMenuItem toolbarSubMenuNavigation = new CheckMenuItem("Navigation");
toolbarSubMenuNavigation.setOnAction(new EventHandler<ActionEvent>()
{
#Override
public void handle(ActionEvent e)
{
DataTabs.toolbarSubMenuNavigation = toolbarSubMenuNavigation;
// call here the getter setter and send boolean flag
System.out.println("subsystem1 #1 Enabled!");
}
});
// class with tabs
public static CheckMenuItem toolbarSubMenuNavigation;
public static CheckMenuItem getToolbarSubMenuNavigation()
{
return toolbarSubMenuNavigation;
}
public static void setToolbarSubMenuNavigation(CheckMenuItem toolbarSubMenuNavigation)
{
DataTabs.toolbarSubMenuNavigation = toolbarSubMenuNavigation;
}
// below
abPane.visibleProperty().bind(toolbarSubMenuNavigation.selectedProperty());
I get NPE when I run the code.
You can easely tell to your tab to be visible when you check the box in one line
yourTab.visibleProperty().bind(yourCheckBox.selectedProperty());
And just with this line your tabpane will be visible only when it's checked
I'm working in java me. I'm trying to switch between visual designs using ok Commands and back Commands. I have a form displayable which I named formA in my main class A.java and a formB in another class B.java . I used an ok Command in formA which on selection, is supposed to take the user to formB.
I created a reference to B.java in my main class A.java constructor
B b;
// A.java constructor
public A() {
b = new B(this);
}
now I could call the getFormB method from my commandAction in formA. Then I added a backCommand which is supposed to take me back to formA in A.java and I tried creating a reference in B.java same way I did in A.java but I get a SecurityException MIDletManager ERROR at runtime. I was adviced to add an A attribute to my B class and receive the instance as a constructor parameter so I can call the getFormA() method to switch to formA in A.java
A a;
B(A a) {
this.a = a;
}
in command action I did ds on the backCommand:
switchDisplayable ( null , a.getFormA());
This compiled, but at runtime on hitting the BACK key from formB I get java/lang/NullPointerException.
Can anyone tell me why this happended and how to fix it please. All I'm trying to acheive is the backCommand to take the user back to formA from formB
If your A class extends Form or your A class is Displayable, then in the Back command, you can just tell switchDisplayable(null, a).
If your A class is not a Form, then make sure your A class has the following methods:
public Form getFormA() {
return ...; // return the `Form` here so you will not get NullPointerException
}
UPDATE:
If you're using NetBeans, you can open Flow tab and drag backCommand from formB to formA. NetBeans will generate the required code for you.
If you code by hand, then it will looks like the following:
import javax.microedition.lcdui.*;
import javax.microedition.midlet.*;
public class ExampleMidlet extends MIDlet {
private Display display;
private Form formA;
private Form formB;
private Command formA_next;
private Command formB_back;
public void startApp() {
if (display==null) {
display = Display.getDisplay(this);
formA = new Form("Form A");
formA_next = new Command("Next", Command.SCREEN, 0);
formA.addCommand(formA_next);
formA.setCommandListener(new CommandListener() {
public void commandAction(Command c, Displayable d) {
if (c==formA_next) {
display.setCurrent(formB);
}
}
});
formB = new Form("Form B");
formB_back = new Command("Back", Command.BACK, 0);
formB.addCommand(formB_back);
formB.setCommandListener(new CommandListener() {
public void commandAction(Command c, Displayable d) {
if (c==formB_back) {
display.setCurrent(formA);
}
}
});
}
display.setCurrent(formA);
}
public void pauseApp() {
}
public void destroyApp(boolean unconditional) {
}
}
I don't know how you code your Form, but it seems that a is null. Maybe you can show me the full code. Passing this in constructor is generally not recommended. By the way, you still need a 'main' class that extends MIDlet right? Then there will be 3 classes, such as:
ExampleMiddlet.java (this is where you put your MIDlet lifecycle, such as startApp(), pauseApp(), etc):
import javax.microedition.lcdui.*;
import javax.microedition.midlet.*;
public class ExampleMidlet extends MIDlet {
private Display display;
private Form formA, formB;
public void startApp() {
if (display==null) {
display = Display.getDisplay(this);
formA = new FormA(this);
formB = new FormB(this);
}
display.setCurrent(formA);
}
public Form getFormA() {
return formA;
}
public Form getFormB() {
return formB;
}
public void pauseApp() {
}
public void destroyApp(boolean unconditional) {
}
}
FormA.java (this is where you put the content of your Form):
import javax.microedition.lcdui.*;
public class FormA extends Form {
private Command cmdNext;
public FormA(final ExampleMidlet midlet) {
super("Form A");
append("This is form A.");
cmdNext = new Command("Next", Command.SCREEN, 0);
addCommand(cmdNext);
setCommandListener(new CommandListener() {
public void commandAction(Command c, Displayable d) {
Display.getDisplay(midlet).setCurrent(midlet.getFormB());
}
});
}
}
FormB.java (this is where you put the content of your Form):
import javax.microedition.lcdui.*;
public class FormB extends Form {
private Command cmdBack;
public FormB(final ExampleMidlet midlet) {
super("Form B");
append("This is form B.");
cmdBack = new Command("Back", Command.SCREEN, 0);
addCommand(cmdBack);
setCommandListener(new CommandListener() {
public void commandAction(Command c, Displayable d) {
Display.getDisplay(midlet).setCurrent(midlet.getFormA());
}
});
}
}