How can I do a sprite to jump with moveYModifier when I touch the screen - sprite

I'm still new with programming android. I have a problem with my game project. The problem is I have a problem with moveYModifier for sprite to jump when I touch the screen. Other problem is I got an error when I try to make a touch event method. Can somebody help me, so I can understand how to write correctly the method. I do not use engine extension because I think it's enough by using moveYModifier. I already search the answer but I still confuse about it. Thanks.
here my code :
import org.anddev.andengine.engine.Engine;
import org.anddev.andengine.engine.camera.Camera;
import org.anddev.andengine.engine.options.EngineOptions;
import org.anddev.andengine.engine.options.EngineOptions.ScreenOrientation;
import org.anddev.andengine.engine.options.resolutionpolicy.RatioResolutionPolicy;
import org.anddev.andengine.entity.modifier.MoveYModifier;
import org.anddev.andengine.entity.modifier.SequenceEntityModifier;
import org.anddev.andengine.entity.scene.Scene;
import org.anddev.andengine.entity.scene.Scene.IOnSceneTouchListener;
import org.anddev.andengine.entity.scene.background.AutoParallaxBackground;
import org.anddev.andengine.entity.scene.background.ParallaxBackground.ParallaxEntity;
import org.anddev.andengine.entity.sprite.AnimatedSprite;
import org.anddev.andengine.entity.sprite.Sprite;
import org.anddev.andengine.entity.util.FPSLogger;
import org.anddev.andengine.input.touch.TouchEvent;
import org.anddev.andengine.opengl.texture.TextureOptions;
import org.anddev.andengine.opengl.texture.atlas.bitmap.BitmapTextureAtlas;
import org.anddev.andengine.opengl.texture.atlas.bitmap.BitmapTextureAtlasTextureRegionFactory;
import org.anddev.andengine.opengl.texture.region.TextureRegion;
import org.anddev.andengine.opengl.texture.region.TiledTextureRegion;
import org.anddev.andengine.ui.activity.BaseGameActivity;
public class KetigaMainActivity extends BaseGameActivity implements IOnSceneTouchListener{
private int CAMERA_WIDTH = 800;
private int CAMERA_HEIGHT = 480;
private BitmapTextureAtlas bitmapTextureAtlas;
private TiledTextureRegion playerTextureRegion;
private BitmapTextureAtlas autoParallaxBackgroundTexture;
private TextureRegion parallaxLayerBack;
private TextureRegion parallaxLayerMid;
private TextureRegion parallaxLayerFront;
private TextureRegion parallaxLayerBackMid;
private int jumpHeight = 100;
private int jumpDuration = 2;
private int playerX = CAMERA_WIDTH/2;
private int playerY = CAMERA_HEIGHT - playerTextureRegion.getTileHeight() - (parallaxLayerFront.getHeight()/3);
#Override
public Engine onLoadEngine() {
final Camera camera = new Camera(0, 0, CAMERA_WIDTH, CAMERA_HEIGHT);
return new Engine(new EngineOptions(true, ScreenOrientation.LANDSCAPE, new RatioResolutionPolicy(CAMERA_WIDTH, CAMERA_HEIGHT), camera));
}
#Override
public void onLoadResources(){
BitmapTextureAtlasTextureRegionFactory.setAssetBasePath("gfx/");
this.bitmapTextureAtlas = new BitmapTextureAtlas(512, 256, TextureOptions.BILINEAR_PREMULTIPLYALPHA);
this.playerTextureRegion = BitmapTextureAtlasTextureRegionFactory.createTiledFromAsset(this.bitmapTextureAtlas, this, "ulat10.png",0,0,4,2);
this.autoParallaxBackgroundTexture = new BitmapTextureAtlas(1024, 1024, TextureOptions.DEFAULT);
this.parallaxLayerFront = BitmapTextureAtlasTextureRegionFactory.createFromAsset(this.autoParallaxBackgroundTexture, this, "tanah6.png",0,810);
this.parallaxLayerBack = BitmapTextureAtlasTextureRegionFactory.createFromAsset(this.autoParallaxBackgroundTexture, this, "background1.png",0,0);
this.parallaxLayerBackMid = BitmapTextureAtlasTextureRegionFactory.createFromAsset(this.autoParallaxBackgroundTexture, this, "gunung3.png",0,490);
this.parallaxLayerMid = BitmapTextureAtlasTextureRegionFactory.createFromAsset(this.autoParallaxBackgroundTexture, this, "awan5.png",0,700);
this.mEngine.getTextureManager().loadTextures(this.bitmapTextureAtlas, this.autoParallaxBackgroundTexture);
}
#Override
public Scene onLoadScene(){
new Scene();
this.mEngine.registerUpdateHandler(new FPSLogger());
final Scene scene = new Scene();
final AutoParallaxBackground autoParallaxBackground = new AutoParallaxBackground(0, 0, 0, 5);
autoParallaxBackground.attachParallaxEntity(new ParallaxEntity(0.0f, new Sprite(0, CAMERA_HEIGHT - this.parallaxLayerBack.getHeight(), this.parallaxLayerBack)));
autoParallaxBackground.attachParallaxEntity(new ParallaxEntity(-1/4.0f, new Sprite(0, CAMERA_HEIGHT - this.parallaxLayerBackMid.getHeight() - (parallaxLayerFront.getHeight()/6), this.parallaxLayerBackMid)));
autoParallaxBackground.attachParallaxEntity(new ParallaxEntity(-1/2.0f, new Sprite(0, 0,this.parallaxLayerMid)));
autoParallaxBackground.attachParallaxEntity(new ParallaxEntity(-3.0f, new Sprite(0, CAMERA_HEIGHT - this.parallaxLayerFront.getHeight(), this.parallaxLayerFront)));
scene.setBackground(autoParallaxBackground);
AnimatedSprite player = new AnimatedSprite(playerX, playerY, this.playerTextureRegion);
player.setScaleCenterY(this.playerTextureRegion.getTileHeight());
player.animate(new long[]{100, 100, 100},0 ,2, true);
scene.setOnSceneTouchListener(this);
scene.attachChild(player);
return scene;
}
#Override
public void onLoadComplete(){
}
#Override
public boolean onSceneTouchEvent(Scene pScene, TouchEvent pSceneTouchEvent) {
if (pSceneTouchEvent.isActionDown()) {
jump(); // this where I got an error
}
return false;
}
public boolean jump(AnimatedSprite player){
final MoveYModifier moveUpModifier = new MoveYModifier(jumpDuration /2, playerY, playerY + jumpHeight);
final MoveYModifier moveDownModivier = new MoveYModifier(jumpDuration /2, playerY + jumpHeight, playerY );
final SequenceEntityModifier modifier = new SequenceEntityModifier(moveUpModifier, moveDownModivier);
player.registerEntityModifier(new SequenceEntityModifier (modifier));
return true;
}
}

#Override
public boolean onSceneTouchEvent(Scene pScene, TouchEvent pSceneTouchEvent)
{
if (pSceneTouchEvent.isActionDown())
{
jump(player);
}
return false;
}

You can use the JumpModifier instead
public boolean jump(AnimatedSprite player){
//your innitial y-position
final float innitialYPosition = 120;
//-140 means jump upward, positive move downward
JumpModifier jumpModifier = new JumpModifier(1, fromX, toX, fromY, toY, -140, new IEntityModifier.IEntityModifierListener() {
#Override
public void onModifierStarted(IModifier<IEntity> pModifier, IEntity pItem) {
animatedSprite.stopAnimation(0);
}
#Override
public void onModifierFinished(IModifier<IEntity> pModifier, IEntity pItem) {
animatedSprite.animate(50);
animatedSprite.setY(innitialYPosition);
}
});
animatedSprite.registerEntityModifier(jumpModifier);
}

Related

Trying to render a square with vaos and vbos

i am trying to learn how to use vaos and vbos. Right now i am trying to render a square but nothing is rendering on the screen. I am using android studios and OpenGL ES 3.
This is my MainActivity:
package com.example.karno.androidgameprojectv3;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import renderEngine.DisplayManager;
import renderEngine.MainRenderer;
public class MainActivity extends Activity {
DisplayManager gameView;
MainRenderer renderer;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
renderer = new MainRenderer();
gameView = new DisplayManager(this);
gameView.setEGLContextClientVersion(3);
gameView.setRenderer(renderer);
this.setContentView(gameView);
}
#Override
protected void onDestroy(){
// Log.d("------test", "in on destroy");
renderer.loader.cleanUp();
super.onDestroy();
}
}
This is the Loader class where i bind the vaos and vbos:
package renderEngine;
import android.opengl.GLES11;
import android.opengl.GLES20;
import android.opengl.GLES30;
import android.util.Log;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
public class Loader {
private int [] vaos;
private int [] vbos;
private int countVbos = -1;
private int countVaos = -1;
public Loader( int neededVAOs, int neededVBOs){
vaos = new int[neededVAOs];
vbos = new int[neededVBOs];
}
public RawModel loadToVAO(float[] position) {
int vaoID = createVAO();
storeDataInAttributeList(0, 3, position);
unbindVAO();
Log.d("looking for null---", "position = " + position);
return new RawModel(vaoID, position.length/3);
}
private int createVAO() {
countVaos++;
GLES30.glGenVertexArrays(1, vaos, 0);
GLES30.glBindVertexArray(vaos[countVaos]);
return vaos[countVaos];
}
private void storeDataInAttributeList(int attributeNumber, int coordinateSize, float[] data) {
countVbos++;
// GLES30.glGenBuffers(1, vbos);
GLES20.glGenBuffers(1, vbos,0);
// Log.d("------vbo", "vbo id = " + vbos.get(countVbos));
GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, vbos[countVbos]);
FloatBuffer buffer = storeDataInFloatBuffer(data);
// Log.d("looking for null arg", "arg2 = " + vbos.get(countVbos) + ", arg3 = " + buffer);
GLES30.glBufferData(GLES30.GL_ARRAY_BUFFER, vbos[0], buffer, GLES30.GL_STATIC_DRAW);
GLES30.glVertexAttribPointer(attributeNumber, coordinateSize, GLES30.GL_FLOAT, false, 0, 0);
GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, 0);
}
private FloatBuffer storeDataInFloatBuffer(float[] data) {
FloatBuffer buffer = FloatBuffer.allocate(data.length);
buffer.put(data);
buffer.flip();
return buffer;
}
private void unbindVAO() {
// this will unbind the VAO
GLES30.glBindVertexArray(0);
}
public void cleanUp() {
Log.d("--------", "in clean up");
for (int vao : vaos) {
GLES30.glDeleteBuffers(vao, vaos, 0);
}
countVaos = -1;
for (int vbo : vbos) {
GLES20.glDeleteBuffers(vbo, vbos,0);
}
countVbos = -1;
Log.d("--------", "cleaned up.");
}
}
The MainRenderer:
package renderEngine;
import android.opengl.GLES20;
import android.opengl.GLSurfaceView;
import android.util.Log;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
public class MainRenderer implements GLSurfaceView.Renderer {
public Loader loader;
Renderer renderer;
RawModel model;
private static final int NEEDED_VAOS = 1;
private static final int NEEDED_VBOS = 1;
//square
float[] vertecies = {
-0.5f, 0.5f, 0f,
-0.5f, -0.5f, 0f,
0.5f, -0.5f, 0f,
0.5f, -0.5f, 0f,
0.5f, 0.5f, 0f,
-0.5f, 0.5f, 0f,
};
#Override
public void onDrawFrame(GL10 arg0){
// GLES20.glClearColor(0,1,0,1);
// GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
renderer.prepare();
renderer.render(model);
}
#Override
public void onSurfaceChanged(GL10 arg0, int height, int width){
}
#Override
public void onSurfaceCreated(GL10 arg0, EGLConfig config){
// Log.d("check------", "in on surface created.");
loader = new Loader(NEEDED_VAOS, NEEDED_VBOS);
renderer = new Renderer();
model = loader.loadToVAO(vertecies);
}
}
The View:
package renderEngine;
import android.content.Context;
import android.opengl.GLSurfaceView;
public class DisplayManager extends GLSurfaceView {
public DisplayManager(Context context){
super(context);
}
}
The Render class:
package renderEngine;
import android.opengl.GLES11;
import android.opengl.GLES20;
import android.opengl.GLES30;
import android.util.Log;
public class Renderer {
public void prepare(){
GLES11.glClearColor(0,1,0,1);
GLES11.glClear(GLES11.GL_COLOR_BUFFER_BIT);
}
public void render(RawModel model) {
// Log.d("------render","model.getVaoID() = "+ model.getVaoID());
GLES30.glBindVertexArray(model.getVaoID());
GLES30.glEnableVertexAttribArray(0);
GLES11.glDrawArrays(GLES11.GL_TRIANGLES, 0, model.getVertexCount());
GLES20.glDisableVertexAttribArray(0);
GLES30.glBindVertexArray(0);
}
}
The 3d model.
package renderEngine;
public class RawModel
{
private int vaoID;
private int vertexCount;
public RawModel(int vaoID, int vertexCount)
{
this.vaoID = vaoID;
this.vertexCount = vertexCount;
}
/**
* #return the vaoID
*/
public int getVaoID() {
return vaoID;
}
/**
* #return the vertexCount
*/
public int getVertexCount() {
return vertexCount;
}
}
In logcat i am getting:
2019-01-06 20:33:43.667 4618-4657/com.example.karno.androidgameprojectv3 E/emuglGLESv2_enc: a vertex attribute index out of boundary is detected. Skipping corresponding vertex attribute. buf=0x7c2911e22a00
2019-01-06 20:33:43.667 4618-4657/com.example.karno.androidgameprojectv3 E/emuglGLESv2_enc: Out of bounds vertex attribute info: clientArray? 0 attribute 0 vbo 1 allocedBufferSize 1 bufferDataSpecified? 1 wantedStart 0 wantedEnd 72
Any help will be appreciated.
The 2nd parameter of GLES30.glBufferData has to be the size of the buffer in bytes, rather then the named buffer object.
See also Java Code Examples for android.opengl.GLES20.glBufferData() and glBufferData:
GLES30.glBufferData(GLES30.GL_ARRAY_BUFFER,
buffer.capacity() * BYTES_PER_FLOAT, buffer, GLES30.GL_STATIC_DRAW);
Note glBufferData creates and initializes the buffer object's data store, for the buffer object which is currently bound by glBindBuffer.

JavaFX - How to resize a SVG Path right in a TableView

I'm having issues to render a SVG Image in a TableView with a CellFactory.
Im using this code here, but it don't work, the svg image is scaled, but it don't resize.
import javafx.application.Application;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.HBox;
import javafx.scene.shape.SVGPath;
import javafx.scene.shape.Shape;
import javafx.stage.Stage;
public class SVGTable extends Application {
private ObservableList<SVGExample> examples;
public static void main(String[] args) {
launch(args);
}
public SVGTable() {
examples = FXCollections.observableArrayList();
examples.addAll(new SVGExample(289),
new SVGExample(42),
new SVGExample(120));
}
#Override
public void start(Stage primaryStage) throws Exception {
AnchorPane pane = new AnchorPane();
Scene scene = new Scene(pane);
TableView<SVGExample> tableView = new TableView<>();
tableView.setMinWidth(500);
tableView.setMinHeight(400);
tableView.setItems(examples);
final TableColumn<SVGExample, Integer> ping = new TableColumn<>("Ping");
ping.setCellValueFactory(new PropertyValueFactory<>("ping"));
ping.setCellFactory(param -> new PingCell());
tableView.getColumns().add(ping);
pane.getChildren().add(tableView);
primaryStage.setScene(scene);
primaryStage.show();
}
public class SVGExample {
private final IntegerProperty ping = new SimpleIntegerProperty();
public SVGExample(int ping) {
setPing(ping);
}
public int getPing() {
return ping.get();
}
public IntegerProperty pingProperty() {
return ping;
}
public void setPing(int ping) {
this.ping.set(ping);
}
}
public class PingCell extends TableCell<SVGExample, Integer> {
private HBox hBox = new HBox();
private Label label;
private int oldValue;
private PingCell() {
label = new Label();
hBox.setAlignment(Pos.CENTER_LEFT);
oldValue = Integer.MIN_VALUE;
}
#Override
protected void updateItem(final Integer item, final boolean empty) {
if (item != null) {
label.setText(item + "ms");
int i = (item + 50) / 100;
if (i < 1)
i = 1;
if (4 < i)
i = 4;
if (i != oldValue) {
SVGPath svgPath1 = new SVGPath();
svgPath1.setContent("M149.2,8.3L127-13.9c42.4-42.4,98.7-65.8,158.5-65.8c59.8,0,116.1,23.4,158.5,65.8L421.8,8.3c-36.5-36.5-84.9-56.6-136.3-56.6C234.1-48.2,185.7-28.1,149.2,8.3z");
SVGPath svgPath2 = new SVGPath();
svgPath2.setContent("M190.9,50.1l-22.2-22.2C200-3.4,241.4-20.6,285.5-20.6c44.1,0,85.5,17.2,116.8,48.4l-22.2,22.2c-25.3-25.3-58.9-39.2-94.6-39.2C249.8,10.8,216.2,24.8,190.9,50.1z");
SVGPath svgPath3 = new SVGPath();
svgPath3.setContent("M232.7,91.8l-22.2-22.2c20.1-20.1,46.7-31.1,75-31.1s55,11.1,75,31.1l-22.2,22.2c-14.1-14.1-32.9-21.9-52.8-21.9C265.6,69.9,246.8,77.7,232.7,91.8z");
SVGPath svgPath4 = new SVGPath();
svgPath4.setContent("M285.5,98.1c-12.8,0-24.5,5.2-32.9,13.6l32.9,32.9l32.9-32.9C310,103.3,298.3,98.1,285.5,98.1z");
Shape s = SVGPath.union(SVGPath.union(SVGPath.union(svgPath1, svgPath2), svgPath3), svgPath4);
s.setScaleX(0.1);
s.setScaleY(0.1);
hBox.getChildren().clear();
hBox.getChildren().addAll(s, label);
}
setGraphic(hBox);
}
}
}
}
After run, it's look like this:
You can wrap the Shape in a Group to force re-size of layout bounds.
hBox.getChildren().addAll(new Group(s), label);
Scale is a type of transform and according to Javadocs:
Any transform, effect, or state applied to a Group will be applied to all children of that group. Such transforms and effects will NOT be included in this Group's layout bounds, however if transforms and effects are set directly on children of this Group, those will be included in this Group's layout bounds.

Running an infinite loop in a JavaFX(Embedded in javax.swing.JFrame) App

I am trying to run an Infinite loop in my JavaFX app.
An infinite while loop is present in my code in the Kulta.java file.
This loop actually freezes my app.
While the same thing works when I port the app to normal javax.swing.
Now since java.lang.Thread doesn't work for javafx, I came accross javafx.concurrent.Task,
which is not working as intended. As one of the main features of multithreading, i.e. running an infinite loop in a GUI app, is not served properly, please help me with the solution.
This is my code:
Urania.java
import java.awt.Toolkit;
import java.awt.Dimension;
import javax.swing.SwingUtilities;
import static javax.swing.WindowConstants.EXIT_ON_CLOSE;
public class Urania {
public static final Dimension DIMENSION = Toolkit.getDefaultToolkit().getScreenSize();
public static void main(String[] args) {
SwingUtilities.invokeLater(
new Runnable() {
#Override
public void run() {
Kulta kulta = new Kulta();
kulta.setTitle("Abha K Pauri");
kulta.setSize(DIMENSION.width/2, DIMENSION.height/2);
kulta.setLocationRelativeTo(null);
kulta.setDefaultCloseOperation(EXIT_ON_CLOSE);
kulta.setVisible(true);
}
}
);
}
}
And here is my JFrame in which I have embedded my JavaFX app.
Kulta.java
import javax.swing.JFrame
import javafx.embed.swing.JFXPanel;
import javafx.application.Platform;
import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;
import javafx.scene.control.Button;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.concurrent.Task;
public class Kulta extends JFrame {
private JFXPanel fxpanel;
private Scene scene;
private BorderPane borderpane;
private Button button;
public static final String INVOKE = "INVOKE";
public static final String INTERRUPT = "INTERRUPT";
public static final String[] COLORS = new String[]{"yellow", "pink", "green", "blue", "orange"};
public Kulta() {
fxpanel = new JFXPanel();
add(fxpanel);
Platform.runLater(
new Runnable() {
#Override
public void run() {
Kulta.this.setScene();
Kulta.this.setButton();
Kulta.this.setListener();
}
}
);
}
private void setScene() {
borderpane = new BorderPane();
scene = new Scene(borderpane);
fxpanel.setScene(scene);
}
private void setButton() {
button = new Button(INVOKE);
borderpane.setTop(button);
}
private void setListener() {
Event event = new Event();
button.setOnAction(event);
}
private class Event implements EventHandler<ActionEvent> {
#Override
public void handle(ActionEvent event) {
boolean flag = true;
Task<Void> onInvoke = new Task<Void>() {
#Override
public Void call() {
int count = 0;
flag = true;
button.setText(INTERRUPT);
/* This loop freezes the app. */
while(flag) {
borderpane.setStyle("-fx-color: "+COLORS[count]+";");
count++;
if(count == COLORS.length)
count = 0;
}
return null;
}
};
Task<Void> onInterrupt = new Task<Void>() {
#Override
public Void call() {
button.setText(INVOKE);
if(flag)
flag = false; // This will stop the onInvoke thread
return null;
}
};
Task<Void> change = new Task<Void>() {
#Override
public Void call() {
if(button.getText().equals(INVOKE))
onInvoke().run();
else if(button.getText().equals(INTERRUPT))
onInterrupt().run();
}
};
change.run();
}
}
}
How should I write the loop in order to not let the app freeze.
Any code, solution, link or any help in any form will help a lot.
Thanks in advance.

Vertical ProgressBar JavaFX

I have a StackPane with the size of (15px width, 400px height). I want to but a "Vertical ProgressBar" to that StackPane. What I was doing is to rotate the progressbar by 90 degree. However, the progressBar cannot fit in the stackpane with that rotation. It just shows as a small squared progressbar at the center of StackPane.
How can I fixed that?
Sample vertical progress bar.
class UpwardProgress {
private ProgressBar progressBar = new ProgressBar();
private Group progressHolder = new Group(progressBar);
public UpwardProgress(double width, double height) {
progressBar.setMinSize(StackPane.USE_PREF_SIZE, StackPane.USE_PREF_SIZE);
progressBar.setPrefSize(height, width);
progressBar.setMaxSize(StackPane.USE_PREF_SIZE, StackPane.USE_PREF_SIZE);
progressBar.getTransforms().setAll(
new Translate(0, height),
new Rotate(-90, 0, 0)
);
}
public ProgressBar getProgressBar() {
return progressBar;
}
public Group getProgressHolder() {
return progressHolder;
}
}
Used in a sample app.
import javafx.animation.*;
import javafx.application.Application;
import javafx.beans.property.*;
import javafx.scene.*;
import javafx.scene.canvas.*;
import javafx.scene.control.*;
import javafx.scene.image.PixelWriter;
import javafx.scene.layout.*;
import javafx.scene.paint.Color;
import javafx.scene.transform.*;
import javafx.stage.Stage;
import javafx.util.Duration;
import java.util.Random;
class UpwardProgress {
private ProgressBar progressBar = new ProgressBar();
private Group progressHolder = new Group(progressBar);
public UpwardProgress(double width, double height) {
progressBar.setMinSize(StackPane.USE_PREF_SIZE, StackPane.USE_PREF_SIZE);
progressBar.setPrefSize(height, width);
progressBar.setMaxSize(StackPane.USE_PREF_SIZE, StackPane.USE_PREF_SIZE);
progressBar.getTransforms().setAll(
new Translate(0, height),
new Rotate(-90, 0, 0)
);
}
public ProgressBar getProgressBar() {
return progressBar;
}
public Group getProgressHolder() {
return progressHolder;
}
}
public class StarCounter extends Application {
public static final Color INDIA_INK = Color.rgb(35, 39, 50);
private static final int CANVAS_SIZE = 400;
private static final int N_STARS = 1_000;
private final Canvas canvas = new Canvas(CANVAS_SIZE, CANVAS_SIZE);
private final Random random = new Random(42);
private final IntegerProperty visibleStars = new SimpleIntegerProperty(0);
private Timeline timeline;
#Override
public void start(final Stage stage) {
Group root = initProgress();
clearCanvas();
visibleStars.addListener((observable, oldValue, newValue) -> {
if (newValue.intValue() > oldValue.intValue()) {
addStars(newValue.intValue() - oldValue.intValue());
}
});
stage.setScene(
new Scene(
new HBox(canvas, root),
INDIA_INK
)
);
stage.show();
runSimulation();
stage.getScene().setOnMouseClicked(event -> {
resetSimulation();
runSimulation();
});
}
private Group initProgress() {
UpwardProgress upwardProgress = new UpwardProgress(15, 400);
ProgressIndicator bar = upwardProgress.getProgressBar();
bar.setStyle("-fx-base: skyblue; -fx-accent: gold;");
bar.progressProperty().bind(visibleStars.divide(N_STARS * 1.0));
return upwardProgress.getProgressHolder();
}
private void resetSimulation() {
clearCanvas();
if (timeline != null) {
timeline.stop();
timeline = null;
}
}
private void runSimulation() {
timeline = new Timeline(
new KeyFrame(
Duration.seconds(0),
new KeyValue(visibleStars, 0)
),
new KeyFrame(
Duration.seconds(10),
new KeyValue(visibleStars, N_STARS)
)
);
timeline.play();
}
private void clearCanvas() {
canvas.getGraphicsContext2D().setFill(INDIA_INK);
canvas.getGraphicsContext2D().fillRect(0, 0, CANVAS_SIZE, CANVAS_SIZE);
}
private void addStars(int nStarsToAdd) {
GraphicsContext context = canvas.getGraphicsContext2D();
PixelWriter writer = context.getPixelWriter();
for (int i = 0; i < nStarsToAdd; i++) {
writer.setColor(random.nextInt(CANVAS_SIZE), random.nextInt(CANVAS_SIZE), Color.GOLD);
}
}
public static void main(String[] args) {
launch(args);
}
}
There's another alternative to this, which is, to make your own custom vertical progress-bar. Sounds too much but isn't. The advantage of this approach is that this is more consistent in UI and more dynamically approachable. I used the above answer by #jewel but struggled with UI consistency and dynamic behavior of the progress-bar.
The approach being use a vbox for the progress-bar and inside it another vbox for bar.
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.VBox?>
<VBox xmlns="http://javafx.com/javafx/8.0.65" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.device.ui.VerticalProgressBarController">
<children>
<VBox fx:id="progress_bar" alignment="BOTTOM_CENTER" prefHeight="450.0" prefWidth="20.0" style="-fx-border-color: black; -fx-border-radius: 2 2 2 2;">
<children>
<VBox fx:id="bar" prefHeight="0.0" prefWidth="20.0" style="-fx-border-radius: 2 2 2 2;"/>
</children>
</VBox>
</children>
</VBox>
One can adjust the prefHeight of progress-bar and bar dynamically in controller or statically in .fxml file. Since here, only bar was the one I needed to adjust dynamically, so have set its prefHeight as 0 and adjust it appropriately in corresponding controller.
public class VerticalProgressBarController implements Initializable {
#FXML
VBox progress_bar;
#FXML
VBox bar;
private double progress_bar,fixed_capacity;
public void initialize(URL location, ResourceBundle resources) {
progressBarHeight = progress_bar.getPrefHeight();
bar.setMaxHeight(progressBarHeight);
// initial bar color
setGreenBar();
// set the max capacity of the progress bar
fixed_capacity = 100;
// pass in the proportion; here wanted to show 15 on a scale of 100
updateProgressBar(15 / fixed_capacity);
}
public void setGreenBar(){
bar.setStyle("-fx-background-color: green");
}
public void setYellowBar(){
bar.setStyle("-fx-background-color: yellow");
}
public void setRedBar(){
bar.setStyle("-fx-background-color: red");
}
public void updateProgressBar(double progress){
bar.setPrefHeight(progressBarHeight * progress);
if(progress <= .60){
setGreenBar();
} else if(progress > .60 &&
progress <= .75){
setYellowBar();
}else {
setRedBar();
}
}

How do I implement JavaFX in existing WindowBuilder project ?

I am trying to get my head around the JavaFX stuff...
My program is a WindowBuilder based Gui, and I want a JavaFX graph, and a JavaFX live video-feed displayed in my app.
How do I implement it in my code? I have tried this, but I couldn't get it runnning.
The data feed isnt the problem. I just need to view it inside my JFrame as small squares...
Confused now :(
Here is my code: (I am sorry that it is a tad long, but I blame the examplecode from JavaFX :p
import javax.swing.JFrame;
import javax.swing.JTextField;
import javax.swing.UIManager;
import java.awt.Canvas;
import java.awt.SystemColor;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import javax.swing.UIManager.*;
/**
* #author
*
*/
public class MyClientApp extends JFrame {
/**
*
*/
private static final long serialVersionUID = 1L;
protected static final String BufferedWriter = null;
JFrame frame;
private JTextField textFieldUsername;
/**
* Create the application.
*/
public MyClientApp(BufferedWriter serverDataOut, BufferedReader serverDataIn) {
initialize();
}
/**
* Initialize the contents of the frame.
*
* #param serverDataOut
*
*/
private void initialize() {
try {
for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (Exception e) {
// Nimbus Theme not avaliable
}
frame = new JFrame();
frame.setResizable(false);
frame.setTitle("*********** My Program ***********");
frame.setBounds(320, 130, 730, 570);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(null);
Canvas canvasTemp = new Canvas();
canvasTemp.setBackground(SystemColor.window);
canvasTemp.setBounds(6, 277, 380, 255);
frame.getContentPane().add(canvasTemp);
Canvas canvasLevel = new Canvas();
canvasLevel.setBackground(SystemColor.window);
canvasLevel.setBounds(6, 10, 380, 255);
frame.getContentPane().add(canvasLevel);
}
public JFrame frame() {
return frame;
}
}
And here is the main file to get it running for you guys... :
Client.java
import java.io.IOException;
public class Client {
public static void main(String[] args) throws IOException, InterruptedException {
MyClientApp window = new MyClientApp(null, null);
window.frame.setVisible(true);
}
}
The code I want to implement is:
AdvancedLineChartSample.java (from JavaFX)
/**
* Copyright (c) 2008, 2012 Oracle and/or its affiliates.
* All rights reserved. Use is subject to license terms.
*/
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.stage.Stage;
import java.util.ArrayList;
import java.util.List;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Side;
import javafx.scene.Node;
import javafx.scene.chart.LineChart;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.XYChart;
import javafx.scene.chart.XYChart.Series;
import javafx.util.Duration;
/**
* An advanced line chart with a variety of actions and settable properties.
*
* #see javafx.scene.chart.LineChart
* #see javafx.scene.chart.Chart
* #see javafx.scene.chart.NumberAxis
* #see javafx.scene.chart.XYChart
*/
public class AdvancedLineChartSample extends Application {
private void init(Stage primaryStage) {
Group root = new Group();
primaryStage.setScene(new Scene(root));
root.getChildren().add(createChart());
}
protected LineChart<Number, Number> createChart() {
final NumberAxis xAxis = new NumberAxis();
final NumberAxis yAxis = new NumberAxis();
final LineChart<Number,Number> lc = new LineChart<Number,Number>(xAxis,yAxis);
// setup chart
lc.setTitle("Temp Chart");
xAxis.setLabel("tid");
yAxis.setLabel("temp");
// add starting data
XYChart.Series<Number,Number> series = new XYChart.Series<Number,Number>();
series.setName("Dataset 1");
series.getData().add(new XYChart.Data<Number,Number>(20d, 50d));
series.getData().add(new XYChart.Data<Number,Number>(40d, 80d));
series.getData().add(new XYChart.Data<Number,Number>(50d, 90d));
series.getData().add(new XYChart.Data<Number,Number>(70d, 30d));
series.getData().add(new XYChart.Data<Number,Number>(170d, 122d));
lc.getData().add(series);
return lc;
}
#Override public void start(Stage primaryStage) throws Exception {
init(primaryStage);
primaryStage.show();
}
public static void main(String[] args) { launch(args);
}
}
and the StreamingMediaPlayer.java (from JavaFX):
/**
* Copyright (c) 2008, 2012 Oracle and/or its affiliates.
* All rights reserved. Use is subject to license terms.
*/
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.stage.Stage;
import javafx.application.Platform;
import javafx.beans.InvalidationListener;
import javafx.beans.Observable;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.control.Label;
import javafx.scene.control.Slider;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.scene.layout.Priority;
import javafx.scene.layout.Region;
import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;
import javafx.scene.media.MediaPlayer.Status;
import javafx.scene.media.MediaView;
import javafx.util.Duration;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.animation.ParallelTransition;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.scene.paint.Color;
/**
* A media player with controls for play, pause, stop, seek, and volume. This media player is playing media via HTTP Live Streaming, also known as HLS.
*
* #see javafx.scene.media.MediaPlayer
* #see javafx.scene.media.Media
*/
public class StreamingMediaPlayer extends Application {
private static final String MEDIA_URL = "http://download.oracle.com/otndocs/products/javafx/JavaRap/prog_index.m3u8";
private MediaPlayer mediaPlayer;
private void init(Stage primaryStage) {
Group root = new Group();
primaryStage.setScene(new Scene(root));
mediaPlayer = new MediaPlayer(new Media(MEDIA_URL));
mediaPlayer.setAutoPlay(true);
PlayerPane playerPane = new PlayerPane(mediaPlayer);
playerPane.setMinSize(480, 360);
playerPane.setPrefSize(480, 360);
playerPane.setMaxSize(480, 360);
// getStylesheets().add("ensemble/samples/media/OverlayMediaPlayer.css");
root.getChildren().add(playerPane);
}
public void play() {
Status status = mediaPlayer.getStatus();
if (status == Status.UNKNOWN || status == Status.HALTED) {
return;
}
if (status == Status.PAUSED || status == Status.STOPPED || status == Status.READY) {
mediaPlayer.play();
}
}
#Override public void stop() {
mediaPlayer.stop();
}
static class PlayerPane extends BorderPane {
private MediaPlayer mp;
private MediaView mediaView;
private final boolean repeat = false;
private boolean stopRequested = false;
private boolean atEndOfMedia = false;
private Duration duration;
private Slider timeSlider;
private Label playTime;
private Slider volumeSlider;
private HBox mediaTopBar;
private HBox mediaBottomBar;
private ParallelTransition transition = null;
#Override protected void layoutChildren() {
if (mediaView != null && getBottom() != null) {
mediaView.setFitWidth(getWidth());
mediaView.setFitHeight(getHeight() - getBottom().prefHeight(-1));
}
super.layoutChildren();
if (mediaView != null) {
mediaView.setTranslateX((((Pane)getCenter()).getWidth() - mediaView.prefWidth(-1)) / 2);
mediaView.setTranslateY((((Pane)getCenter()).getHeight() - mediaView.prefHeight(-1)) / 2);
}
}
#Override protected double computeMinWidth(double height) {
return mediaBottomBar.prefWidth(-1);
}
#Override protected double computeMinHeight(double width) {
return 200;
}
#Override protected double computePrefWidth(double height) {
return Math.max(mp.getMedia().getWidth(), mediaBottomBar.prefWidth(height));
}
#Override protected double computePrefHeight(double width) {
return mp.getMedia().getHeight() + mediaBottomBar.prefHeight(width);
}
#Override protected double computeMaxWidth(double height) { return Double.MAX_VALUE; }
#Override protected double computeMaxHeight(double width) { return Double.MAX_VALUE; }
public PlayerPane(final MediaPlayer mp) {
this.mp = mp;
setId("player-pane");
mediaView = new MediaView(mp);
Pane mvPane = new Pane() { };
mvPane.setId("media-pane");
mvPane.getChildren().add(mediaView);
setCenter(mvPane);
mediaTopBar = HBoxBuilder.create()
.padding(new Insets(5, 10, 5, 10))
.alignment(Pos.CENTER)
.opacity(1)
.build();
BorderPane.setAlignment(mediaTopBar, Pos.CENTER);
mediaBottomBar = HBoxBuilder.create()
.padding(new Insets(5, 10, 5, 10))
.alignment(Pos.CENTER)
.opacity(1)
.build();
BorderPane.setAlignment(mediaBottomBar, Pos.CENTER);
mp.currentTimeProperty().addListener(new ChangeListener<Duration>() {
#Override
public void changed(ObservableValue<? extends Duration> observable, Duration oldValue, Duration newValue) {
updateValues();
}
});
mp.setOnPlaying(new Runnable() {
public void run() {
if (stopRequested) {
mp.pause();
stopRequested = false;
}
}
});
mp.setOnReady(new Runnable() {
public void run() {
duration = mp.getMedia().getDuration();
updateValues();
}
});
mp.setOnEndOfMedia(new Runnable() {
public void run() {
if (!repeat) {
stopRequested = true;
atEndOfMedia = true;
}
}
});
mp.setCycleCount(repeat ? MediaPlayer.INDEFINITE : 1);
// Time label
Label timeLabel = LabelBuilder.create()
.text("Time")
.minWidth(Control.USE_PREF_SIZE)
.textFill(Color.WHITE)
.build();
mediaTopBar.getChildren().add(timeLabel);
// Time slider
timeSlider = SliderBuilder.create()
.id("media-slider")
.minWidth(240)
.maxWidth(Double.MAX_VALUE)
.build();
timeSlider.valueProperty().addListener(new InvalidationListener() {
public void invalidated(Observable ov) {
if (timeSlider.isValueChanging()) {
// multiply duration by percentage calculated by slider position
if (duration != null) {
mp.seek(duration.multiply(timeSlider.getValue() / 100.0));
}
updateValues();
}
}
});
HBox.setHgrow(timeSlider, Priority.ALWAYS);
mediaTopBar.getChildren().add(timeSlider);
// Play label
playTime = LabelBuilder.create()
.prefWidth(130)
.minWidth(50)
.textFill(Color.WHITE)
.build();
mediaTopBar.getChildren().add(playTime);
// Volume label
Label volumeLabel = LabelBuilder.create()
.text("Vol")
.textFill(Color.WHITE)
.minWidth(Control.USE_PREF_SIZE)
.build();
mediaTopBar.getChildren().add(volumeLabel);
// Volume slider
volumeSlider = SliderBuilder.create()
.id("media-slider")
.prefWidth(120)
.maxWidth(Region.USE_PREF_SIZE)
.minWidth(30)
.build();
volumeSlider.valueProperty().addListener(new InvalidationListener() {
public void invalidated(Observable ov) {
}
});
volumeSlider.valueProperty().addListener(new ChangeListener<Number>() {
#Override
public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
if (volumeSlider.isValueChanging()) {
mp.setVolume(volumeSlider.getValue() / 100.0);
}
}
});
mediaTopBar.getChildren().add(volumeSlider);
setTop(mediaTopBar);
final EventHandler<ActionEvent> backAction = new EventHandler<ActionEvent>() {
public void handle(ActionEvent e) {
mp.seek(Duration.ZERO);
}
};
final EventHandler<ActionEvent> stopAction = new EventHandler<ActionEvent>() {
public void handle(ActionEvent e) {
mp.stop();
}
};
final EventHandler<ActionEvent> playAction = new EventHandler<ActionEvent>() {
public void handle(ActionEvent e) {
mp.play();
}
};
final EventHandler<ActionEvent> pauseAction = new EventHandler<ActionEvent>() {
public void handle(ActionEvent e) {
mp.pause();
}
};
final EventHandler<ActionEvent> forwardAction = new EventHandler<ActionEvent>() {
public void handle(ActionEvent e) {
Duration currentTime = mp.getCurrentTime();
mp.seek(Duration.seconds(currentTime.toSeconds() + 5.0));
}
};
mediaBottomBar = HBoxBuilder.create()
.id("bottom")
.spacing(0)
.alignment(Pos.CENTER)
.children(
ButtonBuilder.create()
.id("back-button")
.text("Back")
.onAction(backAction)
.build(),
ButtonBuilder.create()
.id("stop-button")
.text("Stop")
.onAction(stopAction)
.build(),
ButtonBuilder.create()
.id("play-button")
.text("Play")
.onAction(playAction)
.build(),
ButtonBuilder.create()
.id("pause-button")
.text("Pause")
.onAction(pauseAction)
.build(),
ButtonBuilder.create()
.id("forward-button")
.text("Forward")
.onAction(forwardAction)
.build()
)
.build();
setBottom(mediaBottomBar);
}
protected void updateValues() {
if (playTime != null && timeSlider != null && volumeSlider != null && duration != null) {
Platform.runLater(new Runnable() {
public void run() {
Duration currentTime = mp.getCurrentTime();
playTime.setText(formatTime(currentTime, duration));
timeSlider.setDisable(duration.isUnknown());
if (!timeSlider.isDisabled() && duration. greaterThan(Duration.ZERO) && !timeSlider.isValueChanging()) {
timeSlider.setValue(currentTime.divide(duration).toMillis() * 100.0);
}
if (!volumeSlider.isValueChanging()) {
volumeSlider.setValue((int) Math.round(mp.getVolume() * 100));
}
}
});
}
}
private static String formatTime(Duration elapsed, Duration duration) {
int intElapsed = (int)Math.floor(elapsed.toSeconds());
int elapsedHours = intElapsed / (60 * 60);
if (elapsedHours > 0) {
intElapsed -= elapsedHours * 60 * 60;
}
int elapsedMinutes = intElapsed / 60;
int elapsedSeconds = intElapsed - elapsedHours * 60 * 60 - elapsedMinutes * 60;
if (duration.greaterThan(Duration.ZERO)) {
int intDuration = (int)Math.floor(duration.toSeconds());
int durationHours = intDuration / (60 * 60);
if (durationHours > 0) {
intDuration -= durationHours * 60 * 60;
}
int durationMinutes = intDuration / 60;
int durationSeconds = intDuration - durationHours * 60 * 60 - durationMinutes * 60;
if (durationHours > 0) {
return String.format("%d:%02d:%02d",
elapsedHours, elapsedMinutes, elapsedSeconds);
} else {
return String.format("%02d:%02d",
elapsedMinutes, elapsedSeconds);
}
} else {
if (elapsedHours > 0) {
return String.format("%d:%02d:%02d",
elapsedHours, elapsedMinutes, elapsedSeconds);
} else {
return String.format("%02d:%02d",
elapsedMinutes, elapsedSeconds);
}
}
}
}
#Override public void start(Stage primaryStage) throws Exception {
init(primaryStage);
primaryStage.show();
play();
}
public static void main(String[] args) { launch(args);
}
}
I'm sorry about the long code. Its just the samplecode from JavaFX. You find it here, and here.
That should be quite easy to solve. Let me explain it with the chart example that you've shown.
Add an instance of JFXPanel to your JFrame. In your examples, all components are added to a Stage, which is the JavaFX class to represent a window. So you don't need it here. Instead, you add the components that you want to use to the JFXPanel. See also here (function initAndShowGUI) how to do it.
In the init function of the example, a Scene is created as well as the chart itself. What you have to do to let the chart be shown is not much more than that - create a Scene, fill it with content and pass it to the JFXPanel that you already created.
With a minimum effort you can make your chart example run: Make sure that AdvancedLineChartSample.java is in your build path and that the function createChart is somehow accessible from your JFrame. Then add the chart to your code with something similar to the following snippet.
Group root=new Group();
Scene scene=new Scene(root);
myJFXPanel.setScene(scene);
root.getChildren().add(createChart());
This is just a very quick and dirty solution to run your example without any beautiful code and also I didn't test it. But hopefully it gives you a basic understanding of what's going on to encourage further experiments. By my own experience I can tell you that from this step on, there's a lot of fun to come with JavaFX 2.

Resources