I have a class which extends canvas.I created one more canvas class. But I couldn't switch between them.
Is it possible to switching between canvases in J2ME?
import ...
public class MyMIDlet extends MIDlet{
...
final Canvas1 c1;
final Canvas2 c2;
...
public MyMIDlet(){
c1 = new Canvas1(this);
c2 = new Canvas2(this);
}
...
}
import ...
public class Canvas1 extends Canvas implements CommandListener{
MyMIDlet myMidlet;
Display disp;
Command switchDisp;
...
/**
*constructor
*/
public Canvas1(MyMIDlet myMidlet){
this.MyMIDlet = myMidlet;
disp = myMidlet.getDisplay();
switchDisp = new Command("switch", Command.SCREEN, 0);
this.addCommand(switchDisp);
this.setCommandListener(this);
}
...
public void paint(Graphics g){
g.setColor(255,255,255);
g.drawString("canvas1", 0, 0, 0);
}
...
public void commandAction(Command cmd, Displayable displayable){
disp.setCurrent(myMidlet.c2);
}
}
import ...
public class Canvas2 extends Canvas implements CommandListener{
MyMIDlet myMidlet;
Display disp;
Command switchDisp;
...
/**
*constructor
*/
public Canvas1(MyMIDlet myMidlet){
this.MyMIDlet = myMidlet;
disp = myMidlet.getDisplay();
switchDisp = new Command("switch", Command.SCREEN, 0);
this.addCommand(switchDisp);
this.setCommandListener(this);
}
...
public void paint(Graphics g){
g.setColor(255,255,255);
g.drawString("canvas2", 0, 0, 0);
}
...
public void commandAction(Command cmd, Displayable displayable){
disp.setCurrent(myMidlet.c1);
}
}
Displayable object is an object that has the capability of being placed on the display. A Displayable class implements Displayable interface.
The Display class is the display manager that is instantiated for each active MIDlet and provides methods to retrieve information about the device's display capabilities. A canvas is made visible by calling the Display.setCurrent() method.
A canvas implements the Displayable interface.
A Displayable class is a UI element that can be shown on the device's screen while the Display class abstracts the display functions of an actual device's screen and makes them available to you. It provides methods to show or change the current UI element that you want displayed. Thus, a MIDlet shows a Displayable UI element on a Display using the setCurrent(Displayable element) method of the Display class.
Related
I'm developing an Android game with LibGDX. And I need to find the height of the soft-keyboard the user is using, as I want to display some objects right above the keyboard.
I have read this thread:
how can i get soft keyboard height on android?
But the comment suggests that it doesn't work, and it also seems to be for using with Android SDK. I'm not sure. Does anyone know a way that will definitely work?
If your problem is that your textfields are obscured then I suggest using
void Gdx.input.getTextInput(Input.TextInputListener listener,
java.lang.String title,
java.lang.String text)
instead because that will generate a native modal text input dialog that moves up and down with the keyboard. I have tried to get the height of the keyboard as well but so far I haven't managed.
See answers for this thread as well:
How do libgdx detect keyboard presence
Hopefully someone will find this answer helpful:
There is a workout to detect the exact height of the soft-keyboard which involve the Launcher Activity to send screen dimension to the game when a screen resize event occurs.
First, set a layout listener on the ViewTreeObserver of the rootView of your LauncherActivity:
public class AndroidLauncher extends AndroidApplication {
//...
public void setListenerToRootView() {
final View activityRootView = getWindow().getDecorView().findViewById(android.R.id.content);
activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(keyboardLayoutListener);
}
private ViewTreeObserver.OnGlobalLayoutListener keyboardLayoutListener = new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
Rect visibleDisplayFrame = new Rect();
getWindow().getDecorView().getWindowVisibleDisplayFrame(visibleDisplayFrame);
game.screenResize(visibleDisplayFrame.width(), visibleDisplayFrame.height());
}
};
//...
}
If you try to get the height of the root view, it will not work as most of the games are fullscreen.
Don't forget to add and remove the listener on appropriate occurrences:
#Override
protected void onCreate (Bundle savedInstanceState) {
//...
setListenerToRootView();
}
#Override
protected void onDestroy () {
super.onDestroy();
removeListenerToRootView();
}
public void removeListenerToRootView() {
final View activityRootView = getWindow().getDecorView().findViewById(android.R.id.content);
activityRootView.getViewTreeObserver().removeOnGlobalLayoutListener(keyboardLayoutListener);
}
Next, declare the screenResize method inside the Game Class which will receive the dimensions and send it to the current screen:
public class YourGame extends Game {
//...
public ScreenBase currentScreen;
//...
public void screenResize(float width, float height) {
if(currentScreen != null)
currentScreen.onScreenResize(width, height);
}
//...
}
Every screen that involves a change must implement the onScreenResize method. Introduce an Abstract Base Class of screen that has an abstract method onScreenResize. The currentScreen variable must be set in the constructor:
public abstract class ScreenBase implements Screen {
//...
public ScreenBase(YourGame game) {
//...
this.game = game;
this.game.currentScreen = this;
//....
}
public abstract void onScreenResize(float width, float height);
Implement these in whichever screen you want:
public class LoginScreen extends ScreenBase {
//...
#Override
public void onScreenResize(final float width, final float height) {
if(Gdx.graphics.getHeight() > height) {
Gdx.app.log("LoginScreen", "Height of keyboard: " + (Gdx.graphics.getHeight() - height));
}
}
}
I did a try with effect of the framework, but it has some weird behaviour when I blur a textfield into a Parent, the textfield is positioned at a different place, please take a look :
import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.scene.Scene;
import javafx.scene.control.CheckBox;
import javafx.scene.control.TextField;
import javafx.scene.effect.GaussianBlur;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class BlurTest extends Application {
CTextView subPane = new CTextView(100,100);
#Override
public void start(Stage stage) throws Exception {
VBox myBox = new VBox();
CheckBox chkBlur = new CheckBox("Show");
chkBlur.selectedProperty().addListener(new ChangeListener<Boolean>(){
#Override
public void changed(ObservableValue<? extends Boolean> v,
Boolean oldValue, Boolean newValue) {
if(oldValue)
subPane.getTxt().setEffect(new GaussianBlur());
else
subPane.getTxt().setEffect(null);
}
});
myBox.getChildren().addAll(new TextField("Not blur"), subPane, new TextField("Not blur"), chkBlur);
myBox.setPrefSize(250, 500);
Scene scene = new Scene(myBox);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
And my custom textview :
import javafx.scene.Parent;
import javafx.scene.control.TextField;
public class CTextView extends Parent {
private TextField txt;
public CTextView(double w, double h) {
super();
this.txt = new TextField("Default");
this.txt.setLayoutX(20);
this.txt.setLayoutY(20);
this.getChildren().add(this.txt);
}
public TextField getTxt() {
return txt;
}
}
I don't understand why the textfield is repositioned in the Parent after blur effect.. :/
Thanks for your help
> Why is the textfield repositioned?
The GaussianBlur's default radius value is 10. When this effect applied to the node, that node's local bounds expands extra these blurring radii, but the node's width and height remains the same. The Parent does not apply CSS style and does not layout its children, however as seen in your example, it takes into account the local bounds and repositioned the node.
> Why do the textfield's setLayoutX and setLayoutY not worked?
The Parent does consider the local bounds of its child but it does not layout them according the child's layout values. Use a Region (or its subclasses) which takes care its children layout values.
public class CTextView extends Region {
private TextField txt;
public CTextView(double w, double h) {
super();
this.txt = new TextField("Default");
this.txt.setLayoutX(20);
this.txt.setLayoutY(20);
this.getChildren().add(this.txt);
}
public TextField getTxt() {
return txt;
}
}
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());
}
});
}
}
In my J2ME app, I have some forms, and some threads running on background. If in any of these threads I decide to display a message box or notification bar on top of the app, I have the problem of not knowing in which form I am, therefore I don't know which form to show after the messagebox or notification bar is hidden.
Does anyone have any suggestions?
You can get current form that is already displaying with "Display.getCurrent()".For example this canvas is a SplashScreen that get current form before displays in the screen:
import javax.microedition.lcdui.Canvas;
/* */ import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Form;
/* */ import javax.microedition.lcdui.Graphics;
/* */ import javax.microedition.lcdui.Image;
public class StaticSplashScreen extends Canvas
implements Runnable {
private HelloMIDlet mainMidlet;
private boolean isSplashOver;
private long currentTime;
private long previousTime;
private Form currentForm;
public StaticSplashScreen(HelloMIDlet mid) {
this.mainMidlet = mid;
currentForm = (Form) this.mainMidlet.getDisplay().getCurrent();
this.previousTime = System.currentTimeMillis();
new Thread(this).start();
}
protected void paint(Graphics g) {
g.setColor(255, 255, 255);
g.fillRect(0, 0, getWidth(), getHeight());
g.setColor(0, 0, 0);
g.drawString("In the name of God", 40, 70, 0);
}
public void run() {
while (!this.isSplashOver) {
this.currentTime = System.currentTimeMillis();
if (this.currentTime - this.previousTime >= 10000L) {
this.isSplashOver = true;
}
}
this.mainMidlet.getDisplay().setCurrent(currentForm);
}
}
In this midlet you can see two forms with some commands.When you press "help" in each form,method() calls and SplashScreen diplays and after 10 seconds you can see the form that launched it again:
public class HelloMIDlet extends MIDlet implements CommandListener {
...
public void commandAction (Command command, Displayable displayable) {
...
if (command == helpCommand) {
method ();
}
...
}
public Form getForm () {
if (form == null) {
form = new Form ("Welcome");
form.addCommand (getHelpCommand());
form.setCommandListener (this);
}
return form;
}
public void method () {
if (true) {
StaticSplashScreen sss = new StaticSplashScreen(this);
this.getDisplay().setCurrent(sss);
} else {
}
}
public Form getForm1 () {
if (form1 == null) {
form1 = new Form ("form1");
form1.addCommand (getHelpCommand ());
form1.setCommandListener (this);
}
return form1;
}
}
A ticker is an object that provides scrolling text across the top of the display. A Ticker is associated with the display, not with the screen. You place a Ticker on a screen using the Screen.setTicker(Ticker t) method, as shown in the code below.
You can associate the same Ticker object with multiple screens, however. The implementation renders the Ticker on some constant portion of the display, in this case at the top of the display. Ticker is not an Item. Its derivation directly from java.lang.Object gives you a clue as to why a Ticker can be tied to the display and not to a screen. It doesn't need to be derived from Item, because it really is not something that is placed in a Form.
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Ticker;
import javax.microedition.lcdui.Form;
/**
This class demonstrates use of the Ticker MIDP UI
component class.
#see javax.microedition.lcdui.Gauge
*/
public class TickerDemo extends Form
implements CommandListener
{
private String str =
"This text keeps scrolling until the demo stops...";
private Ticker ticker = new Ticker(str);
private Command back = new Command("Back", Command.BACK, 1);
private static Displayable instance;
/**
Constructor.
*/
public TickerDemo()
{
super("Ticker demo");
instance = this;
addCommand(back);
setTicker(ticker);
setCommandListener(this);
}
...
}
Hope this will help you. Thanks
I want to redirect to the given url:
http://www.silvertouch.mobi/mynino/ninoparent/paypalPayment.php?
by clicking the button in the canvas page. How can it be possible to write platformRequest(url) in other canvas file?
Have you tried passing the midlet reference to the canvas and then calling the midlet processRequest(Url) method in pointerPressed?
public class MyCanvas extends Canvas
{
private MIDLet midlet;
public MyCanvas(MIDlet midlet)
{
this.midlet = midlet;
}
...
public pointerPressed(int x, int y)
{
midlet.processRequest(myUrl);
}
}
platformRequest() is on the MIDlet class. Either pass the class to your canvas, or do something like this:
public class MyMIDlet extends MIDlet {
public static MIDlet m;
protected void startApp() throws MIDletStateChangeException {
MyMIDlet.m = this;
... other initialisation stuff
}
}
Then platformRequest() can be called anywhere via MyMIDlet.m.platformRequest().