How to display a new Canvas from pointerPressed() method? - java-me

On a canvas there is an image and on touch at certain part of the image, I am looking to launch a new Canvas from within pointerPressed() method.
Is it possible? So far I have done the following:
protected void pointerPressed(int x, int y){
if ((x>=164 && x<=173)&&(y>=24 && y<=36)){
disp.setCurrent(new elementDetails());
}
}
and the class is as follows:
//class to show detailed information of elements
class elementDetails extends Canvas{
private Image elmDtlImg;
public elementDetails(){
try{
elmDtlImg = Image.createImage("/details.jpg");
}
catch(IOException e){
System.out.println("Couldn't load Detailed Info image" + e.getMessage());
}
}
public void paint(Graphics g){
//set the drawing color to white
g.setGrayScale(255);
//draw a big white rectangle over the whole screen (over the previous screen)
g.fillRect(0, 0, getWidth(), getHeight());
g.drawImage(elmDtlImg, 0, 0, 20);
}
}
When I run the above code nothing happens. I mean to say that the current image does not change to the new one which I am trying to show in the canvas.
My application keeps on running after the pointer pressed event. It does not crashes. It shows me the coords of other parts of the image correctly. What I am trying to achieve is that; when I click/touch at some particular points of the image it should load a new canvas in place of the old one.

A canvas is made visible by calling the Display.setCurrent() method.You would to retrieve Display from your MIDlet and pass it to your canvas,then use it.I hope this snippet code help you:
//MIDlet:
public class MyMIDlet extends MIDlet{
...
final Canvas1 c1;
final elementDetails c2;
...
public MyMIDlet(){
c1 = new Canvas1(this);
c2 = new elementDetails();
}
...
}
//canvas1:
public class Canvas1 extends Canvas{
MyMIDlet myMidlet;
Display disp;
...
/**
*constructor
*/
public Canvas1(MyMIDlet myMidlet){
this.MyMIDlet = myMidlet;
disp = myMidlet.getDisplay();
}
...
public void paint(Graphics g){
g.setColor(255,255,255);
g.drawString("canvas1", 0, 0, 0);
}
...
protected void pointerPressed(int x, int y){
if ((x>=164 && x<=173)&&(y>=24 && y<=36)){
disp.setCurrent(myMidlet.c2);
}
}
//class to show detailed information of elements
class elementDetails extends Canvas{
private Image elmDtlImg;
public elementDetails(){
try{
elmDtlImg = Image.createImage("/details.jpg");
}
catch(IOException e){
System.out.println("Couldn't load Detailed Info image" + e.getMessage());
}
}
public void paint(Graphics g){
//set the drawing color to white
g.setGrayScale(255);
//draw a big white rectangle over the whole screen (over the previous screen)
g.fillRect(0, 0, getWidth(), getHeight());
g.drawImage(elmDtlImg, 0, 0, 20);
}
}

Related

Water 2D wave effect in JavaFX

how can I implement water 2D wave effect in JavaFX, I have image and want to when click on image a wave(or more) start expanding from that point, just like when we drop a piece rock into the calm water and we see the wave expanding.
This is a conversion of parts of old sun JavaFX 1 ripple generator to JavaFX 2.
It's not the most realistic water ripple effect, but maybe it's enough to get you started creating your own. You could add in a DisplacementMap effect to distort your image as a result of the "waves".
The code uses JavaFX animation timelines to generate expanding concentric circles that gradually fade away of time.
import javafx.animation.*;
import javafx.application.Application;
import static javafx.application.Application.launch;
import javafx.collections.*;
import javafx.event.*;
import javafx.scene.*;
import javafx.scene.input.MouseEvent;
import javafx.scene.paint.*;
import javafx.scene.shape.Circle;
import javafx.stage.*;
import javafx.util.Duration;
public class FishSim extends Application {
private static final Paint SCENE_FILL = new RadialGradient(
0, 0, 300, 300, 500, false, CycleMethod.NO_CYCLE,
FXCollections.observableArrayList(new Stop(0, Color.BLACK), new Stop(1, Color.BLUE))
);
#Override public void start(Stage stage) {
final RippleGenerator rippler = new RippleGenerator();
final Scene scene = new Scene(rippler, 600, 400, SCENE_FILL);
scene.setOnMousePressed(new EventHandler<MouseEvent>() {
#Override public void handle(MouseEvent event) {
rippler.setGeneratorCenterX(event.getSceneX());
rippler.setGeneratorCenterY(event.getSceneY());
rippler.createRipple();
rippler.startGenerating();
}
});
scene.setOnMouseDragged(new EventHandler<MouseEvent>() {
#Override public void handle(MouseEvent event) {
rippler.setGeneratorCenterX(event.getSceneX());
rippler.setGeneratorCenterY(event.getSceneY());
}
});
scene.setOnMouseReleased(new EventHandler<MouseEvent>() {
#Override public void handle(MouseEvent event) {
rippler.stopGenerating();
}
});
stage.setTitle("Click, hold mouse button down and move around to create ripples");
stage.setScene(scene);
stage.setResizable(false);
stage.show();
}
public static void main(String[] args) { launch(args); }
}
/**
* Generates ripples on the screen every 0.5 seconds or whenever
* the createRipple method is called. Ripples grow and fade out
* over 3 seconds
*/
class RippleGenerator extends Group {
private class Ripple extends Circle {
Timeline animation = new Timeline(
new KeyFrame(Duration.ZERO, new KeyValue(radiusProperty(), 0)),
new KeyFrame(Duration.seconds(1), new KeyValue(opacityProperty(), 1)),
new KeyFrame(Duration.seconds(3), new KeyValue(radiusProperty(), 100)),
new KeyFrame(Duration.seconds(3), new KeyValue(opacityProperty(), 0))
);
private Ripple(double centerX, double centerY) {
super(centerX, centerY, 0, null);
setStroke(Color.rgb(200, 200, 255));
}
}
private double generatorCenterX = 100.0;
private double generatorCenterY = 100.0;
private Timeline generate = new Timeline(
new KeyFrame(Duration.seconds(0.5), new EventHandler<ActionEvent>() {
#Override public void handle(ActionEvent event) {
createRipple();
}
}
)
);
public RippleGenerator() {
generate.setCycleCount(Timeline.INDEFINITE);
}
public void createRipple() {
final Ripple ripple = new Ripple(generatorCenterX, generatorCenterY);
getChildren().add(ripple);
ripple.animation.play();
Timeline remover = new Timeline(
new KeyFrame(Duration.seconds(3), new EventHandler<ActionEvent>() {
#Override public void handle(ActionEvent event) {
getChildren().remove(ripple);
ripple.animation.stop();
}
})
);
remover.play();
}
public void startGenerating() {
generate.play();
}
public void stopGenerating() {
generate.stop();
}
public void setGeneratorCenterX(double generatorCenterX) {
this.generatorCenterX = generatorCenterX;
}
public void setGeneratorCenterY(double generatorCenterY) {
this.generatorCenterY = generatorCenterY;
}
}
The original JavaFX 1 fish simulator code that the conversion is based on came from a jfrog repository (which might no longer exist if you click it).
Robert Ladstätter created a 2D water effect sample animation for JavaFX 2 (using Scala). Roberts animation is like viewing the water from the side rather than above, but perhaps some of the concepts might help you.
In this tutorial you can find how to use custom GLSL/HLSL pixel shaders for JavaFX.
And the code for a simple distortion procedural wave in screenSpace in HLSL form:
uniform extern texture ScreenTexture;
sampler ScreenS = sampler_state
{
Texture = <ScreenTexture>;
};
float wave; // pi/.75 is a good default
float distortion; // 1 is a good default
float2 centerCoord; // 0.5,0.5 is the screen center
float4 PixelShader(float2 texCoord: TEXCOORD0) : COLOR
{
float2 distance = abs(texCoord - centerCoord);
float scalar = length(distance);
// invert the scale so 1 is centerpoint
scalar = abs(1 - scalar);
// calculate how far to distort for this pixel
float sinoffset = sin(wave / scalar);
sinoffset = clamp(sinoffset, 0, 1);
// calculate which direction to distort
float sinsign = cos(wave / scalar);
// reduce the distortion effect
sinoffset = sinoffset * distortion/32;
// pick a pixel on the screen for this pixel, based on
// the calculated offset and direction
float4 color = tex2D(ScreenS, texCoord+(sinoffset*sinsign));
return color;
}
technique
{
pass P0
{
PixelShader = compile ps_2_0 PixelShader();
}
}
I hope it helps.

JavaFX ProgressBar: how to change bar color?

I'm trying to change the color of bar in ProgressBar with
pBar.setStyle("-fx-accent: green");
but I have encountered a problem: that doesn't seem to work right for me! (Or I just don't understand something)
here is the code:
public class JavaFXApplication36 extends Application {
#Override
public void start(Stage primaryStage) {
AnchorPane root = new AnchorPane();
ProgressBar pbRed = new ProgressBar(0.4);
ProgressBar pbGreen = new ProgressBar(0.6);
pbRed.setLayoutY(10);
pbGreen.setLayoutY(30);
pbRed.setStyle("-fx-accent: red;"); // line (1)
pbGreen.setStyle("-fx-accent: green;"); // line (2)
root.getChildren().addAll(pbRed, pbGreen);
Scene scene = new Scene(root, 150, 50);
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
}
}
I always get 2 red progressbars with it! It seems that code in line (1) changes the style of ProgressBar class, not the instance.
Another strange moment is that deleting line (1) don't result in 2 green progress bars. So I can figure that line (2) is completely useless!! WHY?! That's definitely getting odd.
Is there any way to set separate colors for separate progressbars?
Answer updated to add a simple non-animated example with multiple progress bars
The code in your question should display two different colored progress bars, the fact that it doesn't is a bug in the JavaFX css processing system. Log the bug against the runtime project here: http://javafx-jira.kenai.com.
As a workaround, instead of calling setStyle on the progress bars, define the accent colors used to color progress bars within a stylesheet and add a style class to the progress bars. Then, you can create multiple progress bars within the same application, all with different colors.
As Uluk points out, you can use JavaFX 2.2 caspian.css in conjunction with the JavaFX 2 css reference guide and the JavaFX 2 css tutorial to determine how to style things.
Here is some sample code which customizes a progress bar based upon the information in those references.
Sample css:
/** progress.css
place in same directory as
ColoredProgressBarStyleSheet.java or SimpleColoredProgressBar.java
ensure build system copies the css file to the build output path */
.root { -fx-background-color: cornsilk; -fx-padding: 15; }
.progress-bar { -fx-box-border: goldenrod; }
.green-bar { -fx-accent: green; }
.yellow-bar { -fx-accent: yellow; }
.orange-bar { -fx-accent: orange; }
.red-bar { -fx-accent: red; }
Simple sample program:
import javafx.application.Application;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.ProgressBar;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
// shows multiple progress bars drawn in different colors.
public class SimpleColoredProgressBar extends Application {
public static void main(String[] args) { launch(args); }
#Override public void start(Stage stage) {
final VBox layout = new VBox(10);
layout.setAlignment(Pos.CENTER);
layout.getChildren().setAll(
new ColoredProgressBar("red-bar", 0.2),
new ColoredProgressBar("orange-bar", 0.4),
new ColoredProgressBar("yellow-bar", 0.6),
new ColoredProgressBar("green-bar", 0.8)
);
layout.getStylesheets().add(getClass().getResource("progress.css").toExternalForm());
stage.setScene(new Scene(layout));
stage.show();
}
class ColoredProgressBar extends ProgressBar {
ColoredProgressBar(String styleClass, double progress) {
super(progress);
getStyleClass().add(styleClass);
}
}
}
Simple sample program output:
More complicated sample program with a single animated progress bar which changes color dynamically depending on the amount of progress made:
import javafx.animation.*;
import javafx.application.Application;
import javafx.beans.value.*;
import javafx.event.*;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.Duration;
// shows a progress bar whose bar changes color depending on the amount of progress.
public class ColoredProgressBarStyleSheet extends Application {
public static void main(String[] args) { launch(args); }
private static final String RED_BAR = "red-bar";
private static final String YELLOW_BAR = "yellow-bar";
private static final String ORANGE_BAR = "orange-bar";
private static final String GREEN_BAR = "green-bar";
private static final String[] barColorStyleClasses = { RED_BAR, ORANGE_BAR, YELLOW_BAR, GREEN_BAR };
#Override public void start(Stage stage) {
final ProgressBar bar = new ProgressBar();
final Timeline timeline = new Timeline(
new KeyFrame(Duration.millis(0), new KeyValue(bar.progressProperty(), 0)),
new KeyFrame(Duration.millis(3000), new KeyValue(bar.progressProperty(), 1))
);
Button reset = new Button("Reset");
reset.setOnAction(new EventHandler<ActionEvent>() {
#Override public void handle(ActionEvent event) {
timeline.playFromStart();
}
});
bar.progressProperty().addListener(new ChangeListener<Number>() {
#Override public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
double progress = newValue == null ? 0 : newValue.doubleValue();
if (progress < 0.2) {
setBarStyleClass(bar, RED_BAR);
} else if (progress < 0.4) {
setBarStyleClass(bar, ORANGE_BAR);
} else if (progress < 0.6) {
setBarStyleClass(bar, YELLOW_BAR);
} else {
setBarStyleClass(bar, GREEN_BAR);
}
}
private void setBarStyleClass(ProgressBar bar, String barStyleClass) {
bar.getStyleClass().removeAll(barColorStyleClasses);
bar.getStyleClass().add(barStyleClass);
}
});
final VBox layout = new VBox(10);
layout.setAlignment(Pos.CENTER);
layout.getChildren().setAll(bar, reset);
layout.getStylesheets().add(getClass().getResource("progress.css").toExternalForm());
stage.setScene(new Scene(layout));
stage.show();
timeline.play();
}
}
More complicated sample program output:
You should to override (or customize) the style with JavaFX CSS selectors. See caspian.css for more information. In your own stylesheet define:
.progress-bar .bar {
-fx-background-color:
-fx-box-border,
linear-gradient(to bottom, derive(-fx-accent,95%), derive(-fx-accent,10%)),
red; /* this line is the background color of the bar */
-fx-background-insets: 0, 1, 2;
-fx-padding: 0.416667em; /* 5 */
}
For those who want a simple answer (and without needing to add CSS files):
ProgressBar pbGreen = new ProgressBar(0.6);
pbGreen.setStyle("-fx-accent: green");

J2ME Sprite frames

I am trying to paint only one part of Image. The image human is 159x22 length.
In that image there is 8 human bodies (2 left, 2 right and etc.). If i try to set the Frame to humanSprite.setFrame(1); I will get an error since I specified in the Sprite constructor the size of an Image so there is only one frame.
Well I have tried to divide it by 8 and Ill getjava.lang.IllegalArgumentException`.
Here is the class :
package org.pack.rhynn;
import java.io.IOException;
import javax.microedition.lcdui.game.GameCanvas;
import javax.microedition.lcdui.game.Sprite;
import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;
import java.util.Random;
public class play extends GameCanvas implements Runnable{
int sleep = 30;
private Image map;
private Sprite mapSprite;
private Image human;
private Sprite humanSprite;
private int humanX = getWidth() /2;
private int humanY = getHeight() /2;
public play(){
super(false);
}
public void start(){
try {
map = Image.createImage("/mapas.png");
human = Image.createImage("/human.PNG");
} catch (IOException ioex) {
System.out.println(ioex);
}
mapSprite = new Sprite(map);
mapSprite.defineReferencePixel(100, 150);
mapSprite.setRefPixelPosition(0, 0);
humanSprite = new Sprite(human,159,22);
humanSprite.defineReferencePixel(1, 10);
humanSprite.setRefPixelPosition(humanX, humanY);
Thread thr = new Thread(this);
thr.start();
}
public void run(){
while(true){
updateScreen(getGraphics());
try{
Thread.sleep(sleep);
}catch(Exception e){}
}
}
private void createBackground(Graphics g){
g.setColor(0x000000);
g.fillRect(0, 0, getWidth(), getHeight());
}
private void updateScreen(Graphics g){
createBackground(g);
mapSprite.setRefPixelPosition(0, 0);
mapSprite.paint(g);
humanSprite.setRefPixelPosition(humanX, humanY);
humanSprite.setFrame(0);
humanSprite.setPosition(50,50);
humanSprite.paint(g);
flushGraphics();
}
}
The problem seems to be with your image. All frames must have the same width and height and the image final width and hight must be a multiple of them.
For example, let's say all your frames are in a single row. If the frame width is 19 and you have 8 frames, the final image width must be 152.

LWUIT progress bar

I want to show a progress bar indicating loading application at the beginning.
How can that be done? I have created a gauge but I think it cannot be implemented in LWUIT form..
Based on my comment, You can use progress bar. And also you can use slider component for instead of showing progress bar in LWUIT.
The best way is to use canvas. You can reuse the class in all your apps and it is very efficient. Create a class, say like a class named Splash:
public class Splash extends Canvas {
private final int height;
private final int width;
private int current = 0;
private final int factor;
private final Timer timer = new Timer();
Image AppLogo;
MayApp MIDlet;
/**
*
* #param mainMIDlet
*/
public Splash(MyApp mainMIDlet) {
this.MIDlet = mainMIDlet;
setFullScreenMode(true);
height = getHeight();
width = this.getWidth();
factor = width / 110;
repaint();
timer.schedule(new draw(), 1000, 01);
}
/**
*
* #param g
*/
protected void paint(Graphics g) {
try {//if you want to show your app logo on the splash screen
AppLogo = javax.microedition.lcdui.Image.createImage("/appLogo.png");
} catch (IOException io) {
}
g.drawImage(AppLogo, getWidth() / 2, getHeight() / 2, javax.microedition.lcdui.Graphics.VCENTER | javax.microedition.lcdui.Graphics.HCENTER);
g.setColor(255, 255, 255);
g.setColor(128, 128, 0);//the color for the loading bar
g.fillRect(30, (height / 2) + 100, current, 6);//the thickness of the loading bar, make it thicker by changing 6 to a higher number and vice versa
}
private class draw extends TimerTask {
public void run() {
current = current + factor;
if (current > width - 60) {
timer.cancel();
try {
//go back to your midlet or do something
} catch (IOException ex) {
}
} else {
repaint();
}
Runtime.getRuntime().gc();//cleanup after yourself
}
}
}
and in your MIDlet:
public class MyApp extends MIDlet {
Splash splashScreen = new Splash(this);
public MyApp(){
}
public void startApp(){
try{
Display.init(this);
javax.microedition.lcdui.Display.getDisplay(this).setCurrent(splashScreen);
//and some more stuff
} catch (IOException ex){}
}
//continue

displaying image in j2me application

How do I create and display an image in j2me application?
And in which folder can I put that image in my application?
This link has exactly what you are looking for to get started.
Basically, to create the image, you call upon Image.createImage();
Image img = Image.createImage("/imageName.png");
If it is in a sub-folder in the Jar:
Image img = Image.createImage("/subDir/imageName.png");
To display the image, you need to paint it to a Canvas through a Graphics instance that is tied to the Canvas (better visualized in the link above).
public void paint(Graphics g) {
...
g.drawImage(img, 0, 0, Graphics.TOP | Graphics.LEFT);
....
}
You could also use the Graphics.drawRegion function, but here is a link to the JavaDocs for J2ME for you to look through to see what is best for your needs.
To draw an Image on a JavaME MIDlet you need a Canvas to paint it on to. You can do as follow:
Firs you have to place the original image file inside your package (usually inside "res" or one of his subdirectories).
Secondly you need to create a class extending Canvas and implement the paint method:
import java.io.IOException;
import javax.microedition.lcdui.Canvas;
import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;
public class MyCanvas extends Canvas {
private Image image;
public MyCanvas(){
try {
image = Image.createImage("picture.png");
} catch (IOException e) {
e.printStackTrace();
}
}
protected void paint(Graphics g) {
g.drawImage(image, 10, 10, Graphics.TOP | Graphics.LEFT);
}
}
Now you need to create an instance of this class and tell the MIDlet di display it, for example:
import javax.microedition.lcdui.Display;
import javax.microedition.midlet.MIDlet;
import javax.microedition.midlet.MIDletStateChangeException;
public class MyMIDlet extends MIDlet {
public MyMIDlet(){
}
protected void destroyApp(boolean unconditional)
throws MIDletStateChangeException {
}
protected void pauseApp() {
}
protected void startApp() throws MIDletStateChangeException {
Display.getDisplay(this).setCurrent(new MyCanvas());
}
}
Remember that this way the Canvas will be painted only one time and if you change something, you need to call the repaint() method.
This source code builds on previously posted comments:
import java.io.*;
import javax.microedition.io.*;
import javax.microedition.io.file.FileConnection;
import javax.microedition.lcdui.*;
import javax.microedition.midlet.*;
public class ImageLoader extends MIDlet
implements CommandListener, Runnable {
private Display mDisplay;
private Form mForm;
public ImageLoader() {
mForm = new Form("Connecting...");
mForm.addCommand(new Command("Exit", Command.EXIT, 0));
mForm.setCommandListener(this);
}
public void startApp() {
if (mDisplay == null) mDisplay = Display.getDisplay(this);
mDisplay.setCurrent(mForm);
Thread t = new Thread(this);
t.start();
}
public void pauseApp() {}
public void destroyApp(boolean unconditional) {}
public void commandAction(Command c, Displayable s) {
if (c.getCommandType() == Command.EXIT)
notifyDestroyed();
}
public void run() {
FileConnection fc = null;
DataInputStream in = null;
DataOutputStream out = null;
try {
fc = (FileConnection)Connector.open("file:///root1/i.PNG");
int length = (int)fc.fileSize();//possible loss of precision may throw error
byte[] data = null;
if (length != -1) {
data = new byte[length];
in = new DataInputStream(fc.openInputStream());
in.readFully(data);
}
else {
int chunkSize = 512;
int index = 0;
int readLength = 0;
in = new DataInputStream(fc.openInputStream());
data = new byte[chunkSize];
do {
if (data.length < index + chunkSize) {
byte[] newData = new byte[index + chunkSize];
System.arraycopy(data, 0, newData, 0, data.length);
data = newData;
}
readLength = in.read(data, index, chunkSize);
index += readLength;
} while (readLength == chunkSize);
length = index;
}
Image image = Image.createImage(data, 0, length);
ImageItem imageItem = new ImageItem(null, image, 0, null);
mForm.append(imageItem);
mForm.setTitle("Done.");
fc = (FileConnection)Connector.open("file:///root1/x.PNG");
if(!fc.exists()){
try{
fc.create();
}catch(Exception ce){System.out.print("Create Error: " + ce);}
}
out = new DataOutputStream(fc.openOutputStream());
out.write(data);
}
catch (IOException ioe) {
StringItem stringItem = new StringItem(null, ioe.toString());
mForm.append(stringItem);
mForm.setTitle("Done.");
}
finally {
try {
if (in != null) in.close();
if (fc != null) fc.close();
}
catch (IOException ioe) {}
}
}
}
The code is modified from the link Fostah provided here.
It opens an image, displays it, then saves it as x.PNG instead of i.PNG using FileConnection. The tricky thing to watch for is where the file is being saved/loaded from. If your using J2meWTK with Netbeans, then the folder will be displayed in the output window when you run the mobile app. The folder will be something like temp.DefaultColorPhone/filesystem/root1 . That is where you will have to have an image. I'm not sure how to have the temp environment created with the image by default. That means you have to start the mobile app, check where the temp root1/ is located, in your IDE, then drop the image into the folder, then proceed with running the ImageLoader application. I'll try to find out how to automate this by posting a question. Also, Start with a small image, 50x50 (bigger images may cause problems).

Resources