I've seen many examples that write AnimationTimer and KeyListener in Main class but not seen in another class.
I've tried How to write a KeyListener for JavaFX in "VolleyController", but I don't know why it did not work.
First, I used KeyEvent to move the image just like the first code.
The third code is my Main class. I want to rewrite the methods to move images just like the second code.
But I went into some error written in the second code. How can I deal with it?
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.scene.image.ImageView;
import javafx.scene.input.KeyEvent;
public class VolleyController implements EventHandler<KeyEvent> {
double pika1LocationY = 556;
double pika2LocationY = 556;
double pika1LocationX = 0;
double pika2LocationX = 1050;
boolean pika2MoveLeft = false;
boolean pika2MoveRight = false;
boolean pika1MoveLeft = false;
boolean pika1MoveRight = false;
#FXML
ImageView pika1,pika2,ball;
#Override
public void handle(KeyEvent e) {
switch (e.getCode()) {
case ESCAPE:
Main.currentStage.setScene(Main.menuScene);
break;
case UP:
break;
case LEFT:
pika2MoveLeft = true;
break;
case RIGHT:
pika2MoveRight = true;
break;
case T:
break;
case F:
pika1MoveLeft = true;
break;
case H:
pika1MoveRight = true;
break;
}
move();
}
public void released(KeyEvent r) {
switch (r.getCode()) {
case LEFT:
pika2MoveLeft = false;
break;
case RIGHT:
pika2MoveRight = false;
break;
case F:
pika1MoveLeft = false;
break;
case H:
pika1MoveRight = false;
break;
}
}
public void move() {
if(pika1MoveLeft && pika1.getLayoutX()>=0)
pika1.setLayoutX(pika1.getLayoutX()-10);
if(pika1MoveRight && pika1.getLayoutX()<=440 )
pika1.setLayoutX(pika1.getLayoutX()+10);
if(pika2MoveLeft && pika2.getLayoutX()>600)
pika2.setLayoutX(pika2.getLayoutX()-10);
if(pika2MoveRight && pika2.getLayoutX()<1050)
pika2.setLayoutX(pika2.getLayoutX()+10);
}
}
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.scene.image.ImageView;
import javafx.scene.input.KeyEvent;
public class VolleyController implements EventHandler<KeyEvent> {
double pika1LocationY = 556;
double pika2LocationY = 556;
double pika1LocationX = 0;
double pika2LocationX = 1050;
boolean pika2MoveLeft = false;
boolean pika2MoveRight = false;
boolean pika1MoveLeft = false;
boolean pika1MoveRight = false;
#FXML
ImageView pika1,pika2,ball;
//this gives me a syntax error about getScene(), but the following did not
Main.currentStage.getScene().setOnKeyPressed(new EventHandler<KeyEvent>() {
#Override
public void handle(KeyEvent e) {
switch (e.getCode()) {
case ESCAPE:
Main.currentStage.setScene(Main.menuScene);
break;
case UP:
break;
case LEFT:
pika2MoveLeft = true;
break;
case RIGHT:
pika2MoveRight = true;
break;
case T:
break;
case F:
pika1MoveLeft = true;
break;
case H:
pika1MoveRight = true;
break;
}
}}); //this told me to delete tokens
//this did not give me a syntax error
Main.currentStage.getScene().setOnKeyReleased(new EventHandler<KeyEvent>() {
#Override
public void handle(KeyEvent r) {
switch (r.getCode()) {
case LEFT:
pika2MoveLeft = false;
break;
case RIGHT:
pika2MoveRight = false;
break;
case F:
pika1MoveLeft = false;
break;
case H:
pika1MoveRight = false;
break;
}
}
});
AnimationTimer timer=new AnimationTimer() {
#Override
public void handle(long now)
{
int pika1dx=0, pika2dx=0;
if(pika1MoveLeft) pika1dx-=10;
if(pika1MoveRight) pika1dx+=10;
if(pika2MoveLeft) pika2dx-=10;
if(pika2MoveLeft) pika2dx-=10;
PikaMoveBy(pika1dx,pika2dx);
}
};
timer.start();
}
public void PikaMoveBy(int pika1dx,int pika2dx)
{
if(pika1dx==0 || pika2dx==0) return;
final double pika1cx=pika1.getBoundsInLocal().getWidth()/2;
final double pika2cx=pika2.getBoundsInLocal().getWidth()/2;
double pika1x=pika1cx+pika1.getLayoutX()+pika1dx;
double pika2x=pika2cx+pika2.getLayoutX()+pika2dx;
PikaMoveTo(pika1x, pika2x);
}
public void PikaMoveTo(double pika1x, double pika2x)
{
final double pika1cx=pika1.getBoundsInLocal().getWidth()/2;
final double pika2cx=pika2.getBoundsInLocal().getWidth()/2;
if(pika1x-pika1cx>=0 && pika1x+pika1cx<450 && pika2x-pika2cx>600 && pika2x+pika2cx<1050)
{
pika1.relocate(pika1x-pika1cx, pika1_lct_y);
pika2.relocate(pika2x-pika2cx, pika2_lct_y);
}
}
import java.net.URL;
import java.util.ResourceBundle;
import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.image.ImageView;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;
public class Main extends Application {
public static Stage currentStage;
public static Scene menuScene;
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) throws Exception {
currentStage=primaryStage;
Parent root=FXMLLoader.load(getClass().getResource("Menu.fxml"));
Scene MenuScene = new Scene(root);
currentStage.setScene(MenuScene); //use setScene() to switch the scene
currentStage.setTitle("PikaVolley");
currentStage.show();
}
}
To get key handlres and AnimationTimer working use a simple FXML (Volley.fxml):
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.Pane?>
<?import javafx.scene.layout.VBox?>
<VBox spacing="10.0" xmlns="http://javafx.com/javafx/10.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="test.VolleyController">
<children>
<Label alignment="CENTER" contentDisplay="CENTER" prefHeight="17.0" prefWidth="248.0" text="Press Start.Use Arows to set direction" />
<Pane prefHeight="250.0" prefWidth="250.0">
<children>
<ImageView fx:id="ball" fitHeight="50.0" fitWidth="50.0" pickOnBounds="true" preserveRatio="true" />
</children>
</Pane>
<Button fx:id="startBtn" mnemonicParsing="false" onAction="#start" text="Start" />
</children>
</VBox>
And its controller (see comments):
import javafx.animation.AnimationTimer;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.KeyEvent;
public class VolleyController implements EventHandler<KeyEvent> {
//always use publicly available resources when posting
private static final String BALL = "https://cdn3.iconfinder.com/data/icons/softwaredemo/PNG/32x32/Circle_Red.png";
boolean moveRight = false, moveLeft = false, moveUp = false, moveDown = false;
private static final int DX = 1, DY = 1;
#FXML
ImageView ball;
#FXML
Button startBtn;
#FXML
void initialize(){
ball.setImage(new Image(BALL)); //initialize image view
}
#FXML
void start(){
ball.getScene().setOnKeyPressed(this); //add Key press and release handlers to scene
ball.getScene().setOnKeyReleased(this);
//construct and invoke AnimationTimer
AnimationTimer timer = new AnimationTimer(){
#Override
public void handle(long now) {
move(); //repeatedly invoke move
}
};
timer.start();
startBtn.setDisable(true);
}
#Override
public void handle(KeyEvent e) {
moveRight = false; moveLeft = false; moveUp = false; moveDown = false;
//change movement directions based on key events
switch (e.getCode()) {
case UP:
moveUp = true;
break;
case LEFT:
moveLeft = true;
break;
case RIGHT:
moveRight = true;
break;
case DOWN:
moveDown = true;
break;
}
}
//move if any of the direction control booleans is true
private void move() {
if(moveLeft) {
ball.setLayoutX(ball.getLayoutX()-DX);
}else if(moveRight) {
ball.setLayoutX(ball.getLayoutX()+DX);
}else if(moveDown) {
ball.setLayoutY(ball.getLayoutY()+DY);
}else if(moveUp) {
ball.setLayoutY(ball.getLayoutY()-DY);
}
}
}
test it using :
public class Main extends Application {
#Override
public void start(Stage currentStage) throws Exception {
Parent root=FXMLLoader.load(getClass().getResource("Volley.fxml"));
currentStage.setScene(new Scene(root));
currentStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Related
I am using JavaFx to create a front-end to the cli application called spicetify. I am not using an fxml file for the layout instead I am using different classes for layout purposes.
One such class is the Sidebar class. In it I define how the sidebar should look and then create an object of it on the window/page that I need. Whenever I add buttons to the sidebar The colors of the window where the Sidebar object is created go blank/white.
I am unable to find anything by googling and hope that the information provided is enough.
Screenshot of the window without buttons
Screenshot of the window with buttons
Project Structure
Sidebar class:
package spicetify;
import javafx.scene.Parent;
import javafx.scene.control.Button;
import javafx.scene.image.ImageView;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
public class Sidebar {
BaseWindow baseWindow = new BaseWindow();
private String[] buttonIconLocation = {
"file:src/main/resources/spicetify/images/buttons/home.png",
"file:src/main/resources/spicetify/images/buttons/theme.png",
"file:src/main/resources/spicetify/images/buttons/extension.png",
"file:src/main/resources/spicetify/images/buttons/edit.png",
};
private ImageView[] buttonIcon = new ImageView[4];
private VBox sidebar;
private Button[] buttons = new Button[4];
public Sidebar(int height, int width, String html, Parent root){
this.sidebar = new VBox();
this.sidebar.setPrefHeight(height);
this.sidebar.setPrefWidth(width);
this.sidebar.setStyle("-fx-background-color: " + html);
for (int i = 0; i < buttonIcon.length; i++){
buttonIcon[i] = new ImageView(buttonIconLocation[i]);
baseWindow.transform(buttonIcon[i], 50, 50, true);
}
for (int i = 0; i < buttons.length; i++){
buttons[i] = new Button("", buttonIcon[i]);
sidebar.getChildren().add(buttons[i]);
buttons[i].setTranslateX(20);
buttons[i].setTranslateY(i * 100);
buttons[i].setStyle("-fx-background-color: " + html);
}
}
public String[] getButtonIconLocation() {
return buttonIconLocation;
}
public void setButtonIconLocation(String[] buttonIconLocation) {
this.buttonIconLocation = buttonIconLocation;
}
public ImageView[] getButtonIcon() {
return buttonIcon;
}
public void setButtonIcon(ImageView[] buttonIcon) {
this.buttonIcon = buttonIcon;
}
public VBox getSidebar() {
return sidebar;
}
public void setSidebar(VBox sidebar) {
this.sidebar = sidebar;
}
}
BaseWindow class:
package spicetify;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.image.ImageView;
import javafx.stage.Stage;
public class BaseWindow{
private Parent root;
private Scene scene;
private Stage stage;
private String title;
private int width;
private int height;
private int minWidth;
private int minHeight;
private String htmlColor;
public int getMinWidth() {
return minWidth;
}
public void setMinWidth(int minWidth) {
this.minWidth = minWidth;
}
public int getMinHeight() {
return minHeight;
}
public void setMinHeight(int minHeight) {
this.minHeight = minHeight;
}
public String getHtmlColor() {
return htmlColor;
}
public void setHtmlColor(String htmlColor) {
this.htmlColor = htmlColor;
}
public Parent getRoot() {
return root;
}
public void setRoot(Parent root) {
this.root = root;
}
public Scene getScene() {
return scene;
}
public void setScene(Scene scene) {
this.scene = scene;
}
public Stage getStage() {
return stage;
}
public void setStage(Stage stage) {
this.stage = stage;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public int getWidth() {
return width;
}
public void setWidth(int width) {
this.width = width;
}
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
public void transform(ImageView view, int width, int height, boolean preserveRatio){
view.setFitWidth(width);
view.setFitHeight(height);
view.setPreserveRatio(preserveRatio);
}
public void start(Stage stage){
stage.setScene(scene);
stage.setTitle(title);
stage.show();
}
}
HomeWindow class:
package spicetify;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.BorderPane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
public class HomeWindow extends BaseWindow {
private ImageView logoView;
private ImageView preview;
private Parent root;
private Scene scene;
BaseWindow baseWindow = new BaseWindow();
Sidebar sidebar = new Sidebar(baseWindow.getHeight(), 100, "#282828", root);
public HomeWindow(int width, int height, String html){
this.logoView = new ImageView(new Image("file:src/main/resources/spicetify/images/essentials/logo.png"));
this.preview = new ImageView(new Image("file:src/main/resources/spicetify/images/essentials/Preview.png"));
this.root = new BorderPane();
baseWindow.setWidth(width);
baseWindow.setMinWidth(width);
baseWindow.setHeight(height);
baseWindow.setMinHeight(height);
baseWindow.setHtmlColor(html);
}
public void start(Stage stage){
((BorderPane) root).setLeft(sidebar.getSidebar());
baseWindow.transform(logoView, 600, 700, true);
((BorderPane) root).setCenter(logoView);
baseWindow.setStage(stage);
baseWindow.setTitle("Spicetify");
baseWindow.setRoot(root);
baseWindow.setScene(new Scene(baseWindow.getRoot(), baseWindow.getWidth(), baseWindow.getHeight(), Color.web(baseWindow.getHtmlColor())));
baseWindow.getStage().setScene(baseWindow.getScene());
baseWindow.getStage().setMinWidth(baseWindow.getMinWidth());
baseWindow.getStage().setMinHeight(baseWindow.getMinHeight());
baseWindow.getStage().setTitle(baseWindow.getTitle());
baseWindow.getStage().show();
}
}
Default Modena CSS has a gray background in panes.
When controls are loaded CSS will be applied to the entire scene, as controls use CSS.
Without any controls, CSS (for performance in straight rendering of graphics primitives) will only be applied to the scene if you specifically apply it.
For more information, and steps you can take to remove the default color from pane backgrounds, see the related question:
JavaFX 8 tooltip removes transparency of stage
I am currently trying to create a game with falling "asteroids" that a ship has to dodge. I have currently created a pane that is a large circle stacked with multiple smaller circles. Unfortunately, the pane's "hitbox" is a square/rectangle, rather than a circle, which is frustrating. The other alternate way of fixing this would be to create a circle and fill it with an image of an asteroid, but I couldn't find this anywhere. I know of:
circle.setFill(Color.WHATEVER);
but i would like for it to look like an asteroid, not just a simple grey circle falling. To sum it up, how can I set an image to a shape? Or, if there is a way to change the hitbox of a stackpane, a way to do that would also help fix my issue!
Any help is greatly appreciated! Thanks!
EDIT:
Below are the 4 files that will make a simplified version of my game work with the same problem:
DodgerRemake:
package javafxapplication6;
import javafx.animation.AnimationTimer;
import javafx.application.Application;
import javafx.beans.binding.BooleanBinding;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.input.KeyCode;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class DodgerRemake extends Application
{
private Spaceship thisSpaceShip = new Spaceship();
private BoxPane gamePane = new BoxPane(thisSpaceShip);
BorderPane pane = new BorderPane();
private BooleanProperty upPressed = new SimpleBooleanProperty();
private BooleanProperty rightPressed = new SimpleBooleanProperty();
private BooleanProperty downPressed = new SimpleBooleanProperty();
private BooleanProperty leftPressed = new SimpleBooleanProperty();
private BooleanBinding anyPressed = upPressed.or(rightPressed).or(downPressed).or(leftPressed);
protected BorderPane getPane()
{
StackPane centerPane = new StackPane();
centerPane.getChildren().add(gamePane);
pane.setCenter(centerPane);
Button thisButton = new Button("Start");
thisButton.setAlignment(Pos.CENTER);
thisButton.setFocusTraversable(false);
thisButton.setOnAction(new startGame());
pane.setLeft(thisButton);
return pane;
}
#Override
public void start(Stage primaryStage) {
// Create a scene and place it in the stage
Scene scene = new Scene(getPane(), 960, 800);
primaryStage.setTitle("Dodger"); // Set the stage title
primaryStage.setScene(scene); // Place the scene in the stage
primaryStage.setResizable(false);
primaryStage.show(); // Display the stage
scene.setOnKeyPressed(e -> {
if (e.getCode() == KeyCode.UP) {
upPressed.set(true);
}
if (e.getCode() == KeyCode.DOWN) {
downPressed.set(true);
}
if (e.getCode() == KeyCode.RIGHT) {
rightPressed.set(true);
}
if (e.getCode() == KeyCode.LEFT) {
leftPressed.set(true);
}
});
scene.setOnKeyReleased(e -> {
if (e.getCode() == KeyCode.UP) {
upPressed.set(false);
}
if (e.getCode() == KeyCode.DOWN) {
downPressed.set(false);
}
if (e.getCode() == KeyCode.RIGHT) {
rightPressed.set(false);
}
if (e.getCode() == KeyCode.LEFT) {
leftPressed.set(false);
}
});
AnimationTimer timer = new AnimationTimer()
{
#Override
public void handle(long timestamp) {
if (upPressed.get()){
gamePane.moveShipUp();
}
if (downPressed.get()){
gamePane.moveShipDown();
}
if (rightPressed.get()) {
gamePane.moveShipRight();
}
if (leftPressed.get()) {
gamePane.moveShipLeft();
}
}
};
anyPressed.addListener((obs, wasPressed, isNowPressed) ->
{
if (isNowPressed) {
timer.start();
} else {
timer.stop();
}
});
}
class startGame implements EventHandler<ActionEvent>
{
#Override
public void handle(ActionEvent e)
{
gamePane.addSpaceship();
gamePane.startGame();
}
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}
BoxPane:
package javafxapplication6;
import java.util.Random;
import javafx.animation.Animation;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.scene.layout.Pane;
import javafx.util.Duration;
class BoxPane extends Pane
{
private Spaceship spaceShip;
private Timeline asteroids;
private double x;
private double y;
BoxPane(Spaceship thisSpaceShip)
{
spaceShip = thisSpaceShip;
spaceShip.setRotate(180);
}
public void addSpaceship()
{
getChildren().add(spaceShip);
x = 400 - spaceShip.getWidth()/2;
y = 740;
spaceShip.setTranslateX(x);
spaceShip.setTranslateY(y);
}
public void moveShipLeft()
{
if(x > 0)
{
spaceShip.setTranslateX(x-5);
x = x-5;
}
else
{
spaceShip.setTranslateX(0);
x = 0;
}
}
public void moveShipRight()
{
if(x+spaceShip.getWidth() < getWidth())
{
spaceShip.setTranslateX(x+5);
x = x+5;
}
else
{
spaceShip.setTranslateX(getWidth() - spaceShip.getWidth());
x = getWidth() - spaceShip.getWidth();
}
}
public void moveShipUp()
{
if(y > 0)
{
spaceShip.setTranslateY(y-5);
y = y-5;
}
else
{
spaceShip.setTranslateY(0);
y = 0;
}
}
public void moveShipDown()
{
if(y+spaceShip.getHeight() < getHeight())
{
spaceShip.setTranslateY(y+5);
y = y+5;
}
else
{
spaceShip.setTranslateY(getHeight() - spaceShip.getHeight());
y = getHeight() - spaceShip.getHeight();
}
}
public void startGame()
{
//addSpaceship();
asteroids = new Timeline(new KeyFrame(Duration.seconds(.5), e -> displayAsteroid()));
asteroids.setCycleCount(Timeline.INDEFINITE);
asteroids.play();
}
public void displayAsteroid()
{
Asteroid asteroid = new Asteroid();
getChildren().add(asteroid);
Random rand = new Random();
int randomNum = rand.nextInt((int) (getWidth() - asteroid.getWidth()));
asteroid.setY(-200);
asteroid.setX(randomNum);
asteroid.setTranslateY(asteroid.getY());
asteroid.setTranslateX(asteroid.getX());
Timeline timeline = new Timeline();
KeyFrame keyFrame = new KeyFrame(Duration.millis(50), event -> {
if(asteroid.getY() > getHeight()|| asteroid.getBoundsInParent().intersects(spaceShip.getBoundsInParent()))
{
timeline.stop();
getChildren().remove(asteroid);
}
else
{
asteroid.setY(asteroid.getY()+5);
asteroid.setTranslateY(asteroid.getY());
}
});
timeline.setCycleCount(Animation.INDEFINITE);
timeline.getKeyFrames().add(keyFrame);
timeline.play();
}
}
asteroid class:
package javafxapplication6;
import javafx.geometry.Pos;
import java.util.Random;
import java.util.Vector;
import javafx.scene.layout.HBox;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Ellipse;
public class Asteroid extends StackPane
{
private Ellipse asteroid = new Ellipse();
private Ellipse hole1 = new Ellipse();
private Ellipse hole2 = new Ellipse();
private Ellipse hole3 = new Ellipse();
private int speed;
private double y = 0;
private double x = 0;
Asteroid()
{
Random rand = new Random();
int asteroidNum = rand.nextInt(10);
if(asteroidNum < 6)
{
asteroidNum = 0;
}
else if(asteroidNum < 8)
{
asteroidNum = 1;
}
else
{
asteroidNum = 2;
}
StackPane thisAsteroid = new StackPane();
VBox vbox = new VBox();
HBox hbox = new HBox();
vbox.setAlignment(Pos.CENTER);
hbox.setAlignment(Pos.CENTER);
asteroid.setFill(Color.GREY);
asteroid.setStroke(Color.DIMGREY);
hole1.setFill(Color.DIMGREY);
hole1.setStroke(Color.BLACK);
hole2.setFill(Color.DIMGREY);
hole2.setStroke(Color.BLACK);
hole3.setFill(Color.DIMGREY);
hole3.setStroke(Color.BLACK);
switch(asteroidNum)
{
case 0: asteroid1();
vbox.setSpacing(10);
hbox.setSpacing(10);
break;
case 1: asteroid2();
vbox.setSpacing(15);
hbox.setSpacing(15);
break;
case 2: asteroid3();
vbox.setSpacing(25);
hbox.setSpacing(25);
break;
}
int holeLayout = rand.nextInt(3);
switch(holeLayout)
{
case 0: hbox.getChildren().addAll(hole1, hole2);
vbox.getChildren().addAll(hole3, hbox);
thisAsteroid.getChildren().addAll(asteroid, vbox);
break;
case 1: vbox.getChildren().addAll(hole2, hole3);
hbox.getChildren().addAll(vbox, hole1);
thisAsteroid.getChildren().addAll(asteroid, hbox);
break;
case 2: vbox.getChildren().addAll(hole1, hole3);
hbox.getChildren().addAll(hole2, vbox);
thisAsteroid.getChildren().addAll(asteroid, hbox);
break;
case 3: hbox.getChildren().addAll(hole1, hole2);
vbox.getChildren().addAll(hbox, hole3);
thisAsteroid.getChildren().addAll(asteroid, vbox);
break;
}
this.getChildren().add(thisAsteroid);
}
public void asteroid1()
{
speed = 10;
asteroid.setRadiusX(40);
asteroid.setRadiusY(35);
asteroid.setStrokeWidth(3);
hole1.setRadiusX(7);
hole1.setRadiusY(8);
hole2.setRadiusX(9);
hole2.setRadiusY(6);
hole3.setRadiusX(6);
hole3.setRadiusY(5);
}
public void asteroid2()
{
speed = 6;
asteroid.setRadiusX(60);
asteroid.setRadiusY(50);
asteroid.setStrokeWidth(5);
hole1.setRadiusX(10);
hole1.setRadiusY(12);
hole2.setRadiusX(12);
hole2.setRadiusY(10);
hole3.setRadiusX(14);
hole3.setRadiusY(13);
}
public void asteroid3()
{
speed = 4;
asteroid.setRadiusX(100);
asteroid.setRadiusY(90);
asteroid.setStrokeWidth(8);
hole1.setRadiusX(20);
hole1.setRadiusY(18);
hole2.setRadiusX(18);
hole2.setRadiusY(22);
hole3.setRadiusX(23);
hole3.setRadiusY(19);
}
public void setY(double nY)
{
y = nY;
}
public void setX(double nX)
{
x = nX;
}
public double getX()
{
return x;
}
public double getY()
{
return y;
}
public int getSpeed()
{
return speed;
}
}
spaceship class:
package javafxapplication6;
import javafx.geometry.Pos;
import javafx.scene.layout.HBox;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Ellipse;
import javafx.scene.shape.Rectangle;
public class Spaceship extends StackPane
{
private Rectangle leftWingBottom = new Rectangle();
private Rectangle leftWingGun = new Rectangle();
private Rectangle leftWingDesign = new Rectangle();
private Rectangle leftWingAttachment = new Rectangle();
private Rectangle leftTransparent = new Rectangle();
private Rectangle rightWingBottom = new Rectangle();
private Rectangle rightWingGun = new Rectangle();
private Rectangle rightWingDesign = new Rectangle();
private Rectangle rightWingAttachment = new Rectangle();
private Rectangle rightTransparent = new Rectangle();
private Rectangle centerCompartmentBottom = new Rectangle();
private Rectangle centerCompartmentDesign = new Rectangle();
private Ellipse centerCompartmentTop = new Ellipse();
Spaceship()
{
HBox ship = new HBox();
VBox leftWing = new VBox();
VBox rightWing = new VBox();
VBox leftAttachment = new VBox();
VBox rightAttachment = new VBox();
StackPane leftWingStack = new StackPane();
StackPane rightWingStack = new StackPane();
StackPane centerCompartmentShip = new StackPane();
leftTransparent.setFill(Color.TRANSPARENT);
rightTransparent.setFill(Color.TRANSPARENT);
// creates the right wing
rightWingBottom.setHeight(30);
rightWingBottom.setWidth(8);
rightWingBottom.setStrokeWidth(1);
rightWingDesign.setHeight(25);
rightWingDesign.setWidth(3);
rightWingStack.setAlignment(Pos.CENTER);
rightWingStack.getChildren().addAll(rightWingBottom, rightWingDesign);
rightWingGun.setHeight(5);
rightWingGun.setWidth(2);
rightWing.setAlignment(Pos.TOP_CENTER);
rightWing.getChildren().addAll(rightWingStack, rightWingGun);
// creates the left wing and gun
leftWingBottom.setHeight(30);
leftWingBottom.setWidth(8);
leftWingBottom.setStrokeWidth(1);
leftWingDesign.setHeight(25);
leftWingDesign.setWidth(3);
leftWingStack.setAlignment(Pos.CENTER);
leftWingStack.getChildren().addAll(leftWingBottom, leftWingDesign);
leftWingGun.setHeight(5);
leftWingGun.setWidth(2);
leftWing.setAlignment(Pos.TOP_CENTER);
leftWing.getChildren().addAll(leftWingStack, leftWingGun);
// attaches the cockpit and right wing together
rightTransparent.setHeight(5);
rightTransparent.setWidth(5);
rightWingAttachment.setHeight(3);
rightWingAttachment.setWidth(5);
rightAttachment.setAlignment(Pos.TOP_CENTER);
rightAttachment.getChildren().addAll(rightTransparent, rightWingAttachment);
// attaches the cockpit and left wing together
leftTransparent.setHeight(5);
leftTransparent.setWidth(5);
leftWingAttachment.setHeight(3);
leftWingAttachment.setWidth(5);
leftAttachment.setAlignment(Pos.TOP_CENTER);
leftAttachment.getChildren().addAll(leftTransparent, leftWingAttachment);
// creates the cockpit
centerCompartmentBottom.setHeight(25);
centerCompartmentBottom.setWidth(20);
centerCompartmentBottom.setStrokeWidth(2);
centerCompartmentTop.setRadiusX(10);
centerCompartmentTop.setRadiusY(25);
centerCompartmentTop.setStrokeWidth(2);
centerCompartmentDesign.setHeight(25);
centerCompartmentDesign.setWidth(5);
centerCompartmentShip.setAlignment(Pos.TOP_CENTER);
centerCompartmentShip.getChildren().addAll(centerCompartmentTop, centerCompartmentBottom, centerCompartmentDesign);
rightWingBottom.setFill(Color.WHITE);
rightWingBottom.setStroke(Color.GREY);
leftWingBottom.setFill(Color.WHITE);
leftWingBottom.setStroke(Color.GREY);
rightWingGun.setFill(Color.WHITE);
leftWingGun.setFill(Color.WHITE);
rightWingDesign.setFill(Color.TRANSPARENT);
leftWingDesign.setFill(Color.TRANSPARENT);
rightWingAttachment.setFill(Color.WHITE);
rightWingAttachment.setStroke(Color.GREY);
leftWingAttachment.setFill(Color.WHITE);
leftWingAttachment.setStroke(Color.GREY);
centerCompartmentBottom.setFill(Color.WHITE);
centerCompartmentBottom.setStroke(Color.GREY);
centerCompartmentTop.setFill(Color.WHITE);
centerCompartmentTop.setStroke(Color.GREY);
centerCompartmentDesign.setFill(Color.TRANSPARENT);
// adds everything to final hbox
ship.getChildren().addAll(rightWing,
rightAttachment,
centerCompartmentShip,
leftAttachment,
leftWing);
// adds it to the SpaceShip object
this.getChildren().add(ship);
}
}
Hope this helps, thanks!
I'm using javafx to do some table stuff. I want to validate my textfields in the myTextRow Class. In the "setText2" method I check the input if it is not bigger than 6 symbols, but it has no effects at all.
import java.util.ArrayList;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.scene.control.ContentDisplay;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TextArea;
import javafx.util.Callback;
import javafx.application.Application;
import static javafx.application.Application.launch;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
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.Label;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
public class Supermain extends Application {
#Override
public void start(Stage primaryStage) {
ArrayList myindizes=new ArrayList();
final TableView<myTextRow> table = new TableView<>();
table.setEditable(true);
table.setStyle("-fx-text-wrap: true;");
//Table columns
TableColumn<myTextRow, String> clmID = new TableColumn<>("ID");
clmID.setMinWidth(160);
clmID.setCellValueFactory(new PropertyValueFactory<>("ID"));
TableColumn<myTextRow, String> clmtext = new TableColumn<>("Text");
clmtext.setMinWidth(160);
clmtext.setCellValueFactory(new PropertyValueFactory<>("text"));
clmtext.setCellFactory(new TextFieldCellFactory());
TableColumn<myTextRow, String> clmtext2 = new TableColumn<>("Text2");
clmtext2.setMinWidth(160);
clmtext2.setCellValueFactory(new PropertyValueFactory<>("text2"));
clmtext2.setCellFactory(new TextFieldCellFactory());
//Add data
final ObservableList<myTextRow> data = FXCollections.observableArrayList(
new myTextRow(5, "Lorem","bla"),
new myTextRow(2, "Ipsum","bla")
);
table.getColumns().addAll(clmID, clmtext,clmtext2);
table.setItems(data);
HBox hBox = new HBox();
hBox.setSpacing(5.0);
hBox.setPadding(new Insets(5, 5, 5, 5));
Button btn = new Button();
btn.setText("Get Data");
btn.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
for (myTextRow data1 : data) {
System.out.println("data:" + data1.getText2());
}
}
});
hBox.getChildren().add(btn);
BorderPane pane = new BorderPane();
pane.setTop(hBox);
pane.setCenter(table);
primaryStage.setScene(new Scene(pane, 640, 480));
primaryStage.show();
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
public static class TextFieldCellFactory
implements Callback<TableColumn<myTextRow, String>, TableCell<myTextRow, String>> {
#Override
public TableCell<myTextRow, String> call(TableColumn<myTextRow, String> param) {
TextFieldCell textFieldCell = new TextFieldCell();
return textFieldCell;
}
public static class TextFieldCell extends TableCell<myTextRow, String> {
private TextArea textField;
private StringProperty boundToCurrently = null;
public TextFieldCell() {
textField = new TextArea();
textField.setWrapText(true);
textField.setMinWidth(this.getWidth() - this.getGraphicTextGap() * 2);
this.setGraphic(textField);
}
#Override
protected void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (!empty) {
// Show the Text Field
this.setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
// myindizes.add(getIndex());
// Retrieve the actual String Property that should be bound to the TextField
// If the TextField is currently bound to a different StringProperty
// Unbind the old property and rebind to the new one
ObservableValue<String> ov = getTableColumn().getCellObservableValue(getIndex());
SimpleStringProperty sp = (SimpleStringProperty) ov;
if (this.boundToCurrently == null) {
this.boundToCurrently = sp;
this.textField.textProperty().bindBidirectional(sp);
} else if (this.boundToCurrently != sp) {
this.textField.textProperty().unbindBidirectional(this.boundToCurrently);
this.boundToCurrently = sp;
this.textField.textProperty().bindBidirectional(this.boundToCurrently);
}
double height = real_lines_height(textField.getText(), this.getWidth(), 30, 22);
textField.setPrefHeight(height);
textField.setMaxHeight(height);
textField.setMaxHeight(Double.MAX_VALUE);
// if height bigger than the biggest height in the row
//-> change all heights of the row(textfields ()typeof textarea) to this height
// else leave the height as it is
//System.out.println("item=" + item + " ObservableValue<String>=" + ov.getValue());
//this.textField.setText(item); // No longer need this!!!
} else {
this.setContentDisplay(ContentDisplay.TEXT_ONLY);
}
}
}
}
public class myTextRow {
private final SimpleIntegerProperty ID;
private final SimpleStringProperty text;
private final SimpleStringProperty text2;
public myTextRow(int ID, String text,String text2) {
this.ID = new SimpleIntegerProperty(ID);
this.text = new SimpleStringProperty(text);
this.text2 = new SimpleStringProperty(text2);
}
public void setID(int id) {
this.ID.set(id);
}
public void setText(String text) {
this.text.set(text);
}
public void setText2(String text) {
if(text2check(text)){
this.text2.set(text);}
else
{System.out.println("wrong value!!!");}
}
public int getID() {
return ID.get();
}
public String getText() {
return text.get();
}
public StringProperty textProperty() {
return text;
}
public String getText2() {
return text2.get();
}
public StringProperty text2Property() {
return text2;
}
public IntegerProperty IDProperty() {
return ID;
}
public boolean text2check(String t)
{
if(t.length()>6)return false;
return true;
}
}
private static double real_lines_height(String s, double width, double heightCorrector, double widthCorrector) {
HBox h = new HBox();
Label l = new Label("Text");
h.getChildren().add(l);
Scene sc = new Scene(h);
l.applyCss();
double line_height = l.prefHeight(-1);
int new_lines = s.replaceAll("[^\r\n|\r|\n]", "").length();
// System.out.println("new lines= "+new_lines);
String[] lines = s.split("\r\n|\r|\n");
// System.out.println("line count func= "+ lines.length);
int count = 0;
//double rest=0;
for (int i = 0; i < lines.length; i++) {
double text_width = get_text_width(lines[i]);
double plus_lines = Math.ceil(text_width / (width - widthCorrector));
if (plus_lines > 1) {
count += plus_lines;
//rest+= (text_width / (width-widthCorrector)) - plus_lines;
} else {
count += 1;
}
}
//count+=(int) Math.ceil(rest);
count += new_lines - lines.length;
return count * line_height + heightCorrector;
}
private static double get_text_width(String s) {
HBox h = new HBox();
Label l = new Label(s);
l.setWrapText(false);
h.getChildren().add(l);
Scene sc = new Scene(h);
l.applyCss();
// System.out.println("dubbyloop.FXMLDocumentController.get_text_width(): "+l.prefWidth(-1));
return l.prefWidth(-1);
}
}
A rule of the JavaFX Properties pattern is that for a property x, invoking xProperty().setValue(value) should always be identical to invoking setX(value). Your validation makes this not true. The binding your cell implementation uses invokes the setValue method on the property, which is why it bypasses your validation check.
(Side note: in all the code I am going to change the names so that they adhere to proper naming conventions.)
The default way to implement a property in this pattern is:
public class MyTextRow {
private final StringProperty text = new SimpleStringProperty();
public StringProperty textProperty() {
return text ;
}
public final void setText(String text) {
textProperty().set(text);
}
public final String getText() {
return textProperty().get();
}
}
By having the set/get methods delegate to the appropriate property methods, you are guaranteed these rules are enforced, even if the textProperty() methods is overridden in a subclass. Making the set and get methods final ensures that the rule is not broken by a subclass overriding those methods.
One approach might be to override the set and setValue methods in the property, as follows:
public class MyTextRow {
private final StringProperty text2 = new StringPropertyBase() {
#Override
public String getName() {
return "text2";
}
#Override
public Object getBean() {
return MyTextRow.this ;
}
#Override
public void setValue(String value) {
if (text2Check(value)) {
super.setValue(value);
}
}
#Override
public void set(String value) {
if (text2Check(value)) {
super.set(value);
}
}
}
public StringProperty text2Property() {
return text2 ;
}
public final void setText2(String text2) {
text2Property().set(text2);
}
public final String getText2() {
return text2Property().get();
}
// ...
}
however, I think this will break the bidirectional binding that you have with the text property in the TextArea (basically, there is no way to communicate back to the text area when a change is vetoed, so the text area will not know to revert to the previous value). One fix would be to implement your cell using listeners on the properties instead of bindings. You could use a TextFormatter on the text area that simply updates the property and vetoes the text change if the change doesn't occur.
Here is a complete SSCCE using this approach:
import java.util.function.Function;
import java.util.function.UnaryOperator;
import javafx.application.Application;
import javafx.beans.property.Property;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.beans.property.StringPropertyBase;
import javafx.scene.Scene;
import javafx.scene.control.ContentDisplay;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextFormatter;
import javafx.scene.control.TextFormatter.Change;
import javafx.stage.Stage;
public class VetoStringChange extends Application {
#Override
public void start(Stage primaryStage) {
TableView<Item> table = new TableView<>();
table.setEditable(true);
table.getColumns().add(column("Item", Item::nameProperty));
table.getColumns().add(column("Description", Item::descriptionProperty));
for (int i = 1; i <= 20 ; i++) {
table.getItems().add(new Item("Item "+i, ""));
}
primaryStage.setScene(new Scene(table, 600, 600));
primaryStage.show();
}
public static <S> TableColumn<S,String> column(String title, Function<S,Property<String>> property) {
TableColumn<S,String> col = new TableColumn<>(title);
col.setCellValueFactory(cellData -> property.apply(cellData.getValue()));
col.setCellFactory(tc -> new TextAreaCell<S>(property));
col.setPrefWidth(200);
return col ;
}
public static class TextAreaCell<S> extends TableCell<S, String> {
private TextArea textArea ;
public TextAreaCell(Function<S, Property<String>> propertyAccessor) {
textArea = new TextArea();
textArea.setWrapText(true);
textArea.setMinWidth(this.getWidth() - this.getGraphicTextGap() * 2);
textArea.setMaxHeight(Double.MAX_VALUE);
UnaryOperator<Change> filter = c -> {
String proposedText = c.getControlNewText() ;
Property<String> prop = propertyAccessor.apply(getTableView().getItems().get(getIndex()));
prop.setValue(proposedText);
if (prop.getValue().equals(proposedText)) {
return c ;
} else {
return null ;
}
};
textArea.setTextFormatter(new TextFormatter<String>(filter));
this.setGraphic(textArea);
}
#Override
protected void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (!empty) {
if (! textArea.getText().equals(item)) {
textArea.setText(item);
}
// Show the Text Field
this.setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
} else {
this.setContentDisplay(ContentDisplay.TEXT_ONLY);
}
}
}
public static class Item {
private final StringProperty name = new StringPropertyBase() {
#Override
public Object getBean() {
return Item.this;
}
#Override
public String getName() {
return "name" ;
}
#Override
public void set(String value) {
if (checkValue(value)) {
super.set(value);
}
}
#Override
public void setValue(String value) {
if (checkValue(value)) {
super.setValue(value);
}
}
};
private final StringProperty description = new SimpleStringProperty();
public Item(String name, String description) {
setName(name);
setDescription(description);
}
private boolean checkValue(String value) {
return value.length() <= 6 ;
}
public final StringProperty nameProperty() {
return this.name;
}
public final String getName() {
return this.nameProperty().get();
}
public final void setName(final String name) {
this.nameProperty().set(name);
}
public final StringProperty descriptionProperty() {
return this.description;
}
public final String getDescription() {
return this.descriptionProperty().get();
}
public final void setDescription(final String description) {
this.descriptionProperty().set(description);
}
}
public static void main(String[] args) {
launch(args);
}
}
Another approach is to allow a "commit and revert" type strategy on your property:
public class MyTextRow {
private final StringProperty text2 = new SimpleStringProperty();
public MyTextRow() {
text2.addListener((obs, oldText, newText) -> {
if (! checkText2(newText)) {
// sanity check:
if (checkText2(oldText)) {
text2.set(oldText);
}
}
});
}
public StringProperty text2Property() {
return text ;
}
public final void setText2(String text2) {
text2Property().set(text2);
}
public final String getText2() {
return text2Property().get();
}
}
In general I dislike validation by listening for an invalid value and reverting like this, because other listeners to the property will see all the changes, including changes to and from invalid values. However, this might be the best option in this case.
Finally, you could consider vetoing invalid changes as in the first option, and also setting a TextFormatter on the control in the cell that simply doesn't allow text entry that results in an invalid string. This isn't always possible from a usability perspective (e.g. if empty strings are invalid, you almost always want to allow the user to temporarily delete all the text), and it means keeping two validation checks in sync in your code, which is a pain.
When I click on my app first button it stopped working
kindly advice,what can be the issue?
In my code,I am trying to open one layout when it button is click then is open another layout and then when its button is being clicked then is save data in database.
My loginActivity code is -
package com.example.ahmed.vehiclepermitapp;
import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.ContextMenu;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TabHost;
import android.widget.TextView;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.List;
public class LoginActivity extends Activity {
private static final int EDIT=0, DELETE=1;
EditText carTxt, statusTxt;
ImageView contactImageImgView;
List<Contact> Contacts = new ArrayList<Contact>();
ListView contactListView;
Uri imageUri=Uri.parse("android.resource://com.newthinktank.helloworld/drawable/search.png");
DatabaseHandler dbHandler;
int longClickItemIndex;
ArrayAdapter<Contact> contactAdapter;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.login);
final Button loginBtn = (Button) findViewById(R.id.btnLogin);
loginBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
setContentView(R.layout.activity_main);
carTxt = (EditText) findViewById(R.id.txtCar);
statusTxt = (EditText) findViewById(R.id.txtStatus);
contactListView = (ListView) findViewById(R.id.listView);
contactImageImgView = (ImageView) findViewById(R.id.imgViewContactImage);
dbHandler = new DatabaseHandler(getApplicationContext());
registerForContextMenu(contactListView);
contactListView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
#Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
longClickItemIndex = position;
return false;
}
});
TabHost tabHost = (TabHost) findViewById(R.id.tabHost);
tabHost.setup();
TabHost.TabSpec tabSpec = tabHost.newTabSpec("Creator");
tabSpec.setContent(R.id.Creator);
tabSpec.setIndicator("Creator");
tabHost.addTab(tabSpec);
tabSpec = tabHost.newTabSpec("List");
tabSpec.setContent(R.id.List);
tabSpec.setIndicator("List");
tabHost.addTab(tabSpec);
final Button addBtn = (Button) findViewById(R.id.btnLogin);
addBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Contact contact = new Contact(dbHandler.getContactCount(), String.valueOf(carTxt.getText()), String.valueOf(statusTxt.getText()), imageUri);
if (!contactExists(contact)) {
dbHandler.createContact(contact);
Contacts.add(contact);
contactAdapter.notifyDataSetChanged();
Toast.makeText(getApplicationContext(), String.valueOf(carTxt.getText()) + " has been add to list", Toast.LENGTH_SHORT).show();
return;
}
Toast.makeText(getApplicationContext(), String.valueOf(carTxt.getText()) + "already exists. please use different name", Toast.LENGTH_SHORT).show();
}
});
carTxt.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
addBtn.setEnabled(String.valueOf(carTxt.getText()).trim().length() > 0);
}
#Override
public void afterTextChanged(Editable s) {
}
});
contactImageImgView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent, "Select Contact Image"), 1);
}
});
if (dbHandler.getContactCount() != 0)
Contacts.addAll(dbHandler.getAllContacts());
populateList();
}
});}
public void onCreateContextMenu(ContextMenu menu,View view,ContextMenu.ContextMenuInfo menuInfo){
super.onCreateContextMenu(menu,view,menuInfo);
menu.setHeaderIcon(R.drawable.pencil_con);
menu.setHeaderTitle("Option");
menu.add(Menu.NONE,EDIT,menu.NONE,"Edit Option");
menu.add(Menu.NONE,DELETE,menu.NONE,"Delete Option");
}
public boolean onContextItemSelected(MenuItem item){
switch (item.getItemId()){
case EDIT:
dbHandler.updateContact(Contacts.get(longClickItemIndex));
contactAdapter.notifyDataSetChanged();
break;
case DELETE:
dbHandler.deleteContact(Contacts.get(longClickItemIndex));
Contacts.remove(longClickItemIndex);
contactAdapter.notifyDataSetChanged();
break;
}
return super.onContextItemSelected(item);
}
private boolean contactExists(Contact contact){
String name = contact.getCar();
int countactCount = Contacts.size();
for (int i = 0; i < countactCount; i++)
{
if (name.compareToIgnoreCase(Contacts.get(i).getCar()) == 0)
return true;
}
return false;
}
public void onActivityResult(int reqcode, int rescode, Intent data){
if(rescode == RESULT_OK){
if(reqcode == 1){
imageUri = data.getData();
contactImageImgView.setImageURI(data.getData());
}
}
}
private void populateList() {
contactAdapter = new ContactListAdapter();
contactListView.setAdapter(contactAdapter);
}
class ContactListAdapter extends ArrayAdapter<Contact> {
public ContactListAdapter() {
super(LoginActivity.this, R.layout.listview_item, Contacts);
}
#Override
public View getView(int position, View view, ViewGroup parent) {
if (view == null)
view = getLayoutInflater().inflate(R.layout.listview_item, parent, false);
Contact currentContact = Contacts.get(position);
TextView car = (TextView) view.findViewById(R.id.contactname);
car.setText(currentContact.getCar());
TextView status = (TextView) view.findViewById(R.id.status);
status.setText(currentContact.getStatus());
ImageView img = (ImageView) view.findViewById(R.id.img);
img.setImageURI(currentContact.getimageURI());
return view;
}
}
}
it give this error on logcat
09-06 05:05:16.954
4910-4910/com.example.ahmed.vehiclepermitapp E/AndroidRuntime﹕ FATAL EXCEPTION: main
java.lang.NullPointerException
at com.example.ahmed.vehiclepermitapp.LoginActivity$1.onClick(LoginActivity.java:85)
at android.view.View.performClick(View.java:4106)
at android.view.View$PerformClick.run(View.java:17052)
at android.os.Handler.handleCallback(Handler.java:615)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:5059)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:792)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:555)
at dalvik.system.NativeStart.main(Native Method)
Hy there.
I am trying to make a JPanel which reacts to certain events and plays a little animation. For example if I click on a button, it should flash red.(I need this to indicate when a file was successfully saved(green flash), or a error occurred(red flash).
I found some tutorials on animations, but I'm having a hard time changing it to fit my needs. For example most of the tutorials instantiate a Timer at the beginning. But I only need the timer to be active for that short amount of time where the flash is played and than stop. Also I need different animation types.(red flash, green flash...)
This is what I have got so far, which is basically nothing:
package MainPackage;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JPanel;
import javax.swing.Timer;
public class StatusBar extends JPanel implements ActionListener{
Timer t = new Timer(10, this);
boolean stop = false;
Color color;
public void paintComponent (Graphics g) {
super.paintComponent(g);
setBackground(color);
}
public void confirm(){
color = new Color(46, 204, 113);
t.start();
}
public void warning(){
color = Color.red;
t.start();
}
#Override
public void actionPerformed(ActionEvent e) {
repaint();
}
}
Thanks in advance!
public class flashclass extends JFrame{
Thread th;
Color defaultColor, flashColor;
int i;
boolean success;
JPanel p;
public flashclass(){
setSize(200, 200);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
success = false;
defaultColor = new Color(214,217,223);
p = new JPanel();
JButton rbtn = new JButton("Red flash");
JButton gbtn = new JButton("Green flash");
rbtn.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
success = false;
flash(success);
}
});
gbtn.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
success = true;
flash(success);
}
});
p.add(rbtn);
p.add(gbtn);
getContentPane().add(p);
}
public void flash(boolean success){
i=0;
if(!success){
flashColor = Color.red;
}
else{
flashColor = Color.green;
}
th = new Thread(new Runnable() {
#Override
public void run() {
while(i<10){
p.setBackground(flashColor);
i++;
try {
Thread.sleep(10);
} catch (InterruptedException ex) {
Logger.getLogger(NewJFrame.class.getName()).log(Level.SEVERE, null, ex);
}
p.setBackground(defaultColor);
}
}
});
th.start();
}
}
public static void main(String args[]){
new flashclass();
}
}
So here is the finished class:
New animations can be added easily. And they also do not interfere with each other. So multiple states can be triggered simultaneously.
The StatusBar.java
import java.awt.Color;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import javax.swing.JComponent;
import javax.swing.Timer;
public class StatusBar extends JComponent implements ActionListener{
int width;
int height;
boolean bLoad, bWarn, bConfirm, bError;
Timer timer;
Color bgColor;
int xPosLoad, alphaWarn, alphaConfirm, alphaError;
float cntWarn, cntConfirm, cntError;
int cntLoad;
final int barLength = 200;
public StatusBar(Color bg){
width = getWidth();
height = getHeight();
xPosLoad = -barLength;
alphaWarn = 0;
alphaConfirm = 0;
alphaError = 0;
bgColor = bg;
timer = new Timer(10, this);
this.addComponentListener(new ComponentAdapter() {
#Override
public void componentResized(ComponentEvent event) {
width = getWidth();
height = getHeight();
}
});
}
#Override
protected void paintComponent(Graphics g) {
// Background
g.setColor(bgColor);
g.fillRect(0, 0, width, height);
// loading
Graphics2D g2d = (Graphics2D)g;
GradientPaint gp = new GradientPaint(xPosLoad,0, new Color(0,0,0,0), xPosLoad+barLength, 0, new Color(200, 200, 255));
g2d.setPaint(gp);
g2d.fillRect(xPosLoad, 0, barLength, height);
// Green
g.setColor(new Color(20, 210, 60, alphaConfirm));
g.fillRect(0, 0, width, height);
// Yellow
g.setColor(new Color(255, 223, 0, alphaWarn));
g.fillRect(0, 0, width, height);
// Red
g.setColor(new Color(255, 0, 0, alphaError));
g.fillRect(0, 0, width, height);
}
#Override
public void actionPerformed(ActionEvent e) {
// step increase for all active components
boolean toggle = false;
if (bConfirm){
if(cntConfirm < 1){
cntConfirm += 0.01f;
alphaConfirm = lerp(cntConfirm, 255, true);
}else{
bConfirm = false;
cntConfirm = 0;
alphaConfirm = 0;
}
toggle = true;
}
if (bWarn){
if(cntWarn < 1){
cntWarn += 0.01f;
alphaWarn = lerp(cntWarn, 255, true);
}else{
bWarn = false;
cntWarn = 0;
alphaWarn = 0;
}
toggle = true;
}
if (bError){
if(cntError < 1){
cntError += 0.01f;
alphaError = lerp(cntError, 255, true);
}else{
bError = false;
cntError = 0;
alphaError = 0;
}
toggle = true;
}
if (bLoad){
if(cntLoad < 100){
cntLoad += 1;
xPosLoad = (cntLoad * (width + barLength)) / 100 - barLength;
}else{
cntLoad = 0;
xPosLoad = -barLength;
}
toggle = true;
}
repaint();
if (!toggle){
timer.stop();
}
}
private void startTimer(){
if (!timer.isRunning())
timer.start();
}
public void setBG(Color bg){
bgColor = bg;
System.out.println("Color: " + bgColor);
repaint();
}
// Green flash
public void confirm(){
// set values
bConfirm = true;
alphaConfirm = 255;
cntConfirm = 0;
startTimer();
}
//Yellow flash
public void warning(){
// restart values
bWarn = true;
alphaWarn = 255;
cntWarn = 0;
startTimer();
}
//Red Flash
public void error(){
// restart values
bError = true;
alphaError = 255;
cntError = 0;
startTimer();
}
//Blue load
public void loadStart(){
// restart values
bLoad = true;
xPosLoad = -barLength;
cntLoad = 0;
startTimer();
}
public void loadEnd(){
bLoad = false;
xPosLoad = -barLength;
}
private int lerp(float progress, int max, boolean inverse){
float x = progress;
float x2 = (float) Math.pow(x, 4);
float g = x + (1 - x);
float y = (float) ((float) x2 / (float)(Math.pow(g, 4)));
y = Math.min(y, 1);
y = Math.max(y, 0);
int res = (int) (y * max);
if (inverse){
res = max - res;
}
return res;
}
}
And the Example.java
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Example extends JFrame{
public static void main(String[] args){
new Example("Stat Example");
}
public Example(String title){
super(title);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
StatusBar stat = new StatusBar(Color.black);
stat.setPreferredSize(new Dimension(0, 10));
JPanel panel = new JPanel();
JButton bConfirm = new JButton("Confirm");
JButton bWarn = new JButton("Warning");
JButton bErr = new JButton("Error");
JButton bLoadS = new JButton("Start Loading");
JButton bLoadE = new JButton("End Loading");
panel.add(bConfirm);
panel.add(bWarn);
panel.add(bErr);
panel.add(bLoadS);
panel.add(bLoadE);
this.getContentPane().add(stat, BorderLayout.CENTER);
this.getContentPane().add(panel, BorderLayout.SOUTH);
this.pack();
this.setVisible(true);
// Listener
bConfirm.addActionListener(new java.awt.event.ActionListener() {
#Override
public void actionPerformed(ActionEvent event) {
stat.confirm();
}
});
bWarn.addActionListener(new java.awt.event.ActionListener() {
#Override
public void actionPerformed(ActionEvent event) {
stat.warning();
}
});
bErr.addActionListener(new java.awt.event.ActionListener() {
#Override
public void actionPerformed(ActionEvent event) {
stat.error();
}
});
bLoadS.addActionListener(new java.awt.event.ActionListener() {
#Override
public void actionPerformed(ActionEvent event) {
stat.loadStart();
}
});
bLoadE.addActionListener(new java.awt.event.ActionListener() {
#Override
public void actionPerformed(ActionEvent event) {
stat.loadEnd();
}
});
}
}