I got a JavaFX programm and I am not sure how I get the values to determine when the ball hits the target bricks, which are created in two for loops. I got my ball already moving on its own, but I do not have the hitbox of my paddle yet nor my targets. I would like to hear your ideas or startegies to make that work. Thanks for reading!
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.TilePane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Rectangle;
import javafx.scene.text.Font;
import javafx.scene.text.TextAlignment;
import javafx.stage.Stage;
import javafx.util.Duration;
public class Breakout extends Application {
public static void main(String[] args) {
launch(args);
}
private static final int width = 700;
private static final int height = 900;
private boolean gameStarted;
private int rad = 10;
private int ballYPos = width / 2;
private int ballXPos = height / 2;
private int paddleXpos = width / 2;
private int paddleYpos = height - 100;
private int ballXSpeed = 2;
private int ballYSpeed = 2;
#Override
public void start(Stage primaryStage) throws Exception {
Canvas canvas = new Canvas(width, height);
GraphicsContext gc = canvas.getGraphicsContext2D();
Timeline t = new Timeline(new KeyFrame(Duration.millis(10), e -> run(gc)));
t.setCycleCount(Timeline.INDEFINITE);
canvas.setOnMouseClicked(e -> gameStarted = true);
//Kanvas mit KeyHandler, den ich verwenden möchte
canvas.setOnKeyPressed(e -> paddleXpos--);
primaryStage.setTitle("Breakout");
primaryStage.setScene(new Scene(new StackPane(canvas)));
primaryStage.show();
t.play();
}
public void run(GraphicsContext gc) {
gc.setFill(Color.GRAY);
gc.fillRect(0, 0, width, height);
gc.setFill(Color.GREEN);
gc.fillOval(ballXPos, ballYPos, rad, rad);
gc.setFill(Color.BLUE);
gc.fillRect(paddleXpos, paddleYpos, 50, 10);
gc.setFill(Color.RED);
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 5; j++) {
gc.fillRect(j * 130 + 55, i * 30 + 40, 75, 20);
}
}
if (gameStarted) {
ballYPos += ballYSpeed;
ballXPos += ballXSpeed;
if (ballXPos == width - rad || ballXPos == 0) {
ballXSpeed *= -1;
}
if (ballYPos == height - rad || ballYPos == 0) {
ballYSpeed *= -1;
}
}
}
}
Related
I would like to change the colour of a button after I build the scene.
I have to do a battleship. When I place a boat many buttons have to change their colours.
So, I have a function do to it and I test that. I filter the boxes contained in "oceanBoxes" by their coordinates and when I get true I call function putBoatInside.
private void placeGuiBoat(int x, int y, int direction, int size) {
List<Integer> listBoxesBoatNeed;
if(direction == HORIZONTAL) {
listBoxesBoatNeed = IntStream.range(y,y+size).boxed().collect(Collectors.toList());
try {
listBoxesBoatNeed.forEach(e -> oceanBoxes.stream().filter(p->p.getX() == x && p.getY() == e).findFirst().orElse(null).putBoatInside());
} catch(Exception e) {}
}
}
And in Boxe class, I have this
public void putBoatInside() {
this.setStyle("-fx-background-color:#000;");
}
EDIT
Here the minimal reproducible example I made to solve it and see that the problem wasn't there.
Main
package application;
import javafx.scene.layout.GridPane;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import GUI.BtnOcean;
import javafx.application.Application;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.control.Button;
public class Main extends Application {
#Override
public void start(Stage primaryStage) {
try {
GridPane root = new GridPane();
BtnOcean btn = new BtnOcean(1,1);
BtnOcean btn1 = new BtnOcean(1,2);
BtnOcean btn2 = new BtnOcean(1,3);
BtnOcean btn3 = new BtnOcean(1,4);
BtnOcean btn4 = new BtnOcean(1,5);
ArrayList<BtnOcean> ocean = new ArrayList<BtnOcean>(Arrays.asList(btn,btn1,btn2,btn3,btn4));
Button btn5 = new Button("change");
List<Integer> list = IntStream.range(1,5).boxed().collect(Collectors.toList());
btn5.setOnAction(j -> {
list.stream().forEach(e -> ocean.stream().filter( p-> p.getX() == 1 && p.getY() == e ).findFirst().orElse(null).putBoatInside());
});
root.add(btn, 0, 0);
root.add(btn1, 1, 0);
root.add(btn2, 2, 0);
root.add(btn3, 3, 0);
root.add(btn4, 4, 0);
root.add(btn5, 5, 0);
Scene scene = new Scene(root,1200,800);
scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
primaryStage.setScene(scene);
primaryStage.show();
} catch(Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
}
BtnOcean class
package GUI;
import javax.swing.ImageIcon;
import javafx.scene.control.Button;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
public class BtnOcean extends Button{
private int x;
private int y;
private String cssProps = "-fx-background-color:#fff;" +
"-fx-border-color:#000000;"+
"-fx-border-width: 1px;";
public BtnOcean(int x, int y,String text){
this.x = x;
this.y = y;
setMinHeight(60);
setMinWidth(60);
setStyle(cssProps);
setText(text);
}
public BtnOcean(int x, int y){
this.x = x;
this.y = y;
setMinHeight(60);
setMinWidth(60);
setStyle(cssProps);
}
public void putBoatInside() {
System.out.println(this);
this.setStyle("-fx-background-color:#000;");
}
There is no method for triangle only for reactangle and oval?
canvas.getGraphicsContext2D()
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
public class BasicOpsTest extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) {
primaryStage.setTitle("Drawing Operations Test");
Group root = new Group();
Canvas canvas = new Canvas(300, 250);
GraphicsContext gc = canvas.getGraphicsContext2D();
drawShapes(gc);
root.getChildren().add(canvas);
primaryStage.setScene(new Scene(root));
primaryStage.show();
}
private void drawShapes(GraphicsContext gc) {
int firstX = 90;
int secondX = 190;
int thirdX = 10;
int firstY =30;
int secondY =170;
int thirdY =170;
gc.setFill(Color.GREEN);
gc.setStroke(Color.BLUE);
gc.fillPolygon(new double[]{firstX, secondX,thirdX},
new double[]{firstY, secondY, thirdY}, 3);
gc.strokePolygon(new double[]{firstX, secondX,thirdX},
new double[]{firstY, secondY, thirdY}, 3);
gc.setFill(javafx.scene.paint.Color.BLACK);
gc.fillText("1", firstX - 3, firstY - 4);
gc.fillText("2", secondX - 3, secondY - 4);
gc.fillText("3", thirdX - 3, thirdY - 4);
}
}
I got a horizontal fill problem.
I got a app javafx app with a BorderPane.
In the setBottom I would like to add a info-component.
How ever this info-component extends Canvas.
But when I add it it does not fill or resize correct.
I also tried to use a Label and that too did not fill correct but in an other way.
I also tied with a TextField and that filled out and resized the area correct.
Do you guys got any ideas how to add a Canvas that fill out the area correct?
Canvas added
http://snag.gy/seswj.jpg
Label added:
http://snag.gy/6wSy8.jpg
TextField added:
http://snag.gy/7ajUc.jpg
Best regards
Fredrik
Okey here is some code.
My main class:
package a.app;
import java.net.URL;
import javafx.application.Application;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.control.Tooltip;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.scene.layout.Priority;
import javafx.stage.Stage;
public class BannerTest extends Application
{
private Pane mainPanel;
Stage primaryStage;
#Override
public void start(Stage ps) throws Exception
{
primaryStage = ps;
primaryStage.setTitle( "BannerTest" );
mainPanel = createBorderPaneGui();
Scene scene = new Scene(mainPanel, 700, 700);
URL resource = BannerTest.class.getResource("/BannerTest.css");
String externalForm = resource.toExternalForm();
scene.getStylesheets().add( externalForm );
primaryStage.setScene( scene );
primaryStage.setTitle("BannerTest");
primaryStage.show();
}
public static void main(String[] args)
{
launch(args);
}
private Pane createBorderPaneGui()
{
mainPanel = new BorderPane();
GridPane applicationPanel = getApplicationPanel();
BorderedTitledPane borderedTitledPane = new BorderedTitledPane("Hubba", applicationPanel);
((BorderPane)mainPanel).setCenter( borderedTitledPane );
BorderedTitledPane banner = getBanner( 20, mainPanel );
((BorderPane)mainPanel).setBottom( banner );
return mainPanel;
}
private GridPane getApplicationPanel()
{
GridPane applicationPanel = new GridPane();
Label direcoryLabel = new Label("Directory:");
applicationPanel.add(direcoryLabel, 0, 0);
final TextField fileTextField = new TextField();
fileTextField.setEditable(false);
applicationPanel.add(fileTextField, 1, 0);
Button button = new Button("Select more then all you can select, Select more then all you can select");
HBox hBox = new HBox(10);
hBox.setAlignment(Pos.BOTTOM_RIGHT);
hBox.getChildren().add(button);
applicationPanel.add(hBox, 2, 0);
Label infoLabel = new Label("?");
applicationPanel.add(infoLabel, 3, 0);
infoLabel.setTooltip( new Tooltip("Select directory as search root."));
applicationPanel.setGridLinesVisible(true);
return applicationPanel;
}
private BorderedTitledPane getBanner(int height, Pane panel )
{
HBox bannerBox = new HBox(10);
Banner banner = new Banner(height, "", "C:/a/image/image.png", bannerBox);
//Canvas banner = new Canvas();
//Label banner = new Label("Hola");
//TextField banner = new TextField();
bannerBox.setHgrow(banner, Priority.ALWAYS);
bannerBox.getChildren().addAll( banner );
BorderedTitledPane borderedTitledPane = new BorderedTitledPane("Info", bannerBox);
return borderedTitledPane;
}
}
This class uses a style-css:
.mainPanel {
-fx-background-color: #8fbc8f;
}
.applicationPanel {
-fx-padding: 20 20 20 20;
-fx-alignment: top-center;
-fx-background-color: #00FFFF;
-fx-border-color: #FF0000;
-fx-border-width: 20px;
}
.bannerBox {
-fx-alignment: bottom-center;
-fx-background-color: #FFFFFF;
-fx-border-color: #0000FF;
-fx-border-width: 20px;
}
.banner{
-fx-alignment: bottom-center;
-fx-background-color: #00FF00;
}
.label {
-fx-font: 14px Helvetica;
}
.bordered-titled-title {
-fx-background-color: white;
-fx-translate-y: -15;
-fx-translate-x: 10;
}
.bordered-titled-border {
-fx-content-display: top;
-fx-border-insets: 40 40 15 15;
-fx-background-color: white;
-fx-border-color: black;
-fx-border-width: 2;
}
.bordered-titled-content {
-fx-padding: 26 26 26 26;
}
As you can see my main purpose is to display a banner, this banner is a Canvas that extends this class:
package a.app;
import javafx.beans.InvalidationListener;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
public class ResizableWidthCanvas extends Canvas
{
private Double endValue;
public ResizableWidthCanvas(int height)
{
setHeight( height );
InvalidationListener listener = new InvalidationListener(){
public void invalidated(javafx.beans.Observable arg0) {
setEndValue( getWidth() );
draw();
}
};
widthProperty().addListener(listener);
}
private void draw() {
double width = getWidth()-4;
double height = getHeight()-4;
GraphicsContext gc = getGraphicsContext2D();
gc.clearRect(2, 2, width, height);
}
#Override
public boolean isResizable() {
return true;
}
/*
#Override
public double prefWidth(double width) {
return getWidth();
}
*/
#Override
public double prefHeight(double height) {
return getHeight();
}
public Double getEndValue()
{
return endValue;
}
public void setEndValue(Double endValue)
{
this.endValue = endValue;
}
}
The Banner class it self:
package a.app;
import java.io.File;
import javafx.animation.AnimationTimer;
import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.Timeline;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.image.Image;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.util.Duration;
public class Banner extends /*Canvas*/ ResizableWidthCanvas
{
String imageUrl;
String imagePath;
DoubleProperty doublePropertyX = new SimpleDoubleProperty();
DoubleProperty doublePropertyY = new SimpleDoubleProperty();
public Banner(int height, String imageUrl, String imagePath, Pane pane)
{
super(height);
setHeight( height );
widthProperty().bind( pane.widthProperty() );
File file = new File(imagePath);
final Image image = new Image(file.toURI().toString());
Double endValue = new Double( pane.getWidth()-image.getWidth() );
KeyValue keyValue = new KeyValue( doublePropertyX, endValue );
Timeline timeline = new Timeline(
new KeyFrame(Duration.seconds(0),
new KeyValue(doublePropertyX, 0)
),
new KeyFrame(Duration.seconds(3),
keyValue
)
);
timeline.setAutoReverse(true);
timeline.setCycleCount(Timeline.INDEFINITE);
AnimationTimer timer = new AnimationTimer()
{
int r = 0;
int g = 0;
int b = 0;
#Override
public void handle(long now)
{
GraphicsContext gc = getGraphicsContext2D();
if(r < 255)
{
r++;
}
else if(g < 255)
{
g++;
}
else if(b < 255)
{
b++;
}
else
{
r = 0;
g = 0;
b = 0;
}
gc.setFill( Color.rgb(r,g,b) );
gc.fillRect(0, 0, getWidth(), getHeight());
gc.drawImage(image,
doublePropertyX.doubleValue(),
doublePropertyY.doubleValue()+1
);
}
};
timer.start();
timeline.play();
}
}
I also use a BorderTitelPane that looks like:
package a.app;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.control.Label;
import javafx.scene.layout.HBox;
import javafx.scene.layout.StackPane;
public class BorderedTitledPane extends StackPane
{
public BorderedTitledPane(String titleString, Node content)
{
Label title = new Label(" " + titleString + " ");
title.getStyleClass().add("bordered-titled-title");
StackPane.setAlignment(title, Pos.TOP_LEFT);
StackPane contentPane = new StackPane();
content.getStyleClass().add("bordered-titled-content");
contentPane.getChildren().add(content);
getStyleClass().add("bordered-titled-border");
getChildren().addAll(title, contentPane);
}
}
Hope that was all.
The width of your canvas is exactly equal to its container. Its coming out of box because it's starting x position is different. This is happening because in the class Banner, inside the constructor you have mentioned
widthProperty().bind(pane.widthProperty());
This means whatever is the width of the pane that will be set as the width of the canvas.
Instead of this, write the following
pane.widthProperty().addListener(new ChangeListener<Number>() {
#Override
public void changed(ObservableValue<? extends Number> ov, Number t, Number t1) {
setWidth((double)t1 - 70);//You can change the number according to difference in the x position
}
});
I'm working on this code with Barchart and Piechart.
import java.sql.Timestamp;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;
import javafx.application.Application;
import static javafx.application.Application.launch;
import javafx.application.Platform;
import javafx.beans.binding.Bindings;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableObjectValue;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.concurrent.Task;
import javafx.geometry.Bounds;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.chart.BarChart;
import javafx.scene.chart.CategoryAxis;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.PieChart;
import javafx.scene.chart.XYChart;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Label;
import javafx.scene.control.ProgressIndicator;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.scene.text.Text;
import javafx.stage.Stage;
public class MainApp extends Application
{
#Override
public void start(Stage stage) throws Exception
{
Scene scene = new Scene(initGeneralAgentsData(), 800, 800);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args)
{
launch(args);
}
private final StackPane stackPane = new StackPane();
private List<DownloadTrafficObj> obj = new LinkedList<>();
public StackPane initGeneralAgentsData() throws Exception
{
stackPane.setAlignment(Pos.TOP_RIGHT);
stackPane.setStyle("-fx-background-color: white;");
SQLSelect(30);
stackPane.getChildren().addAll(chartChoose());
return stackPane;
}
private List<DownloadTrafficObj> SQLSelect(int history_value)
{
for (int i = 0; i < history_value; i++)
{
obj.add(new DownloadTrafficObj(String.valueOf(randomDate()), Long.valueOf(randomNumber())));
}
return obj;
}
private Timestamp randomDate()
{
long offset = Timestamp.valueOf("2012-01-01 00:00:00").getTime();
long end = Timestamp.valueOf("2013-01-01 00:00:00").getTime();
long diff = end - offset + 1;
Timestamp rand = new Timestamp(offset + (long) (Math.random() * diff));
return rand;
}
private int randomNumber()
{
Random rand = new Random();
int n = rand.nextInt(50) + 1;
return n;
}
public StackPane chartChoose()
{
final ComboBox comboBox = new ComboBox();
comboBox.getItems().addAll("Bar Chart", "Pie Chart");
ComboBox cb = new ComboBox();
cb.getItems().addAll(10, 20, 30, 60);
cb.setValue(30);
final StackPane stack = new StackPane();
comboBox.getSelectionModel().selectedIndexProperty()
.addListener((ObservableValue<? extends Number> observable,
Number oldValue, Number newValue)
-> setVisibility(stack, comboBox)
);
cb.getSelectionModel().selectedIndexProperty()
.addListener((ObservableValue<? extends Number> observable,
Number oldValue, Number newValue)
->
{
SQLSelect((int) cb.getSelectionModel().getSelectedItem());
bc.getData().clear();
generateBarChartData();
}
);
stack.getChildren().add(generateBarChart());
stack.getChildren().add(generatePieChart());
// Placing it after adding rectangle to stack
// will trigger the changelistener to show default rectangle
comboBox.setValue("Bar Chart");
VBox vBox = new VBox();
vBox.setPadding(new Insets(10, 10, 10, 10));
vBox.setSpacing(5);
Label labelon = new Label("Chart type");
Label label = new Label("Days history");
HBox hBossx = new HBox(15, labelon, comboBox, label, cb);
hBossx.setAlignment(Pos.CENTER_RIGHT);
ProgressIndicator progress = new ProgressIndicator();
progress.setMaxSize(90, 90);
Task<ObservableList<DownloadTrafficObj>> task = new Task<ObservableList<DownloadTrafficObj>>()
{
#Override
protected ObservableList<DownloadTrafficObj> call() throws Exception
{
for (int i = 0; i < 99; i++)
{
Thread.sleep(20);
}
return (FXCollections.observableArrayList(obj));
}
};
progress.progressProperty().bind(task.progressProperty());
task.setOnSucceeded(ev ->
{
});
new Thread(task).start();
BorderPane bp = new BorderPane();
bp.centerProperty().bind(
Bindings
.when(task.runningProperty())
.then(progress)
.otherwise((ObservableObjectValue<ProgressIndicator>) stack));
vBox.getChildren().addAll(hBossx, bp);
StackPane root = new StackPane();
root.getChildren().add(vBox);
return root;
}
public void setVisibility(Pane pane, ComboBox comboBox)
{
// Make all children invisible
pane.getChildren().stream().forEach((node) ->
{
node.setVisible(false);
});
// make the selected rectangle visible
int selectedIndex = comboBox.getSelectionModel()
.selectedIndexProperty().getValue();
pane.getChildren().get(selectedIndex).setVisible(true);
}
final CategoryAxis xAxis = new CategoryAxis();
final NumberAxis yAxis = new NumberAxis();
final BarChart<String, Number> bc = new BarChart<>(xAxis, yAxis);
XYChart.Series series1 = new XYChart.Series();
public BarChart<String, Number> generateBarChart()
{
bc.setTitle("Network Download");
xAxis.setLabel("Groups");
yAxis.setLabel("Value");
series1.setName("Network Download");
generateBarChartData();
// TO DO... Very quick fix.
bc.widthProperty().addListener((obs, b, b1) ->
{
// Chart Bar column is not automatically resized. We need to wait for next JavaFX releases to fix this.
Platform.runLater(() -> setMaxBarWidth(bc, xAxis, 40, 10));
});
bc.getData().addAll(series1);
return bc;
}
private void generateBarChartData()
{
obj.stream().map((get) -> new XYChart.Data(get.getDate(), get.getDownloadTraffic())).map((data) ->
{
data.nodeProperty().addListener(new ChangeListener<Node>()
{
#Override
public void changed(ObservableValue<? extends Node> ov, Node oldNode, final Node node)
{
if (node != null)
{
//setNodeStyle(data);
displayLabelForData(data);
}
}
});
return data;
}).forEach((data) ->
{
series1.getData().add(data);
});
}
private void setMaxBarWidth(BarChart<String, Number> bc, CategoryAxis xAxis, double maxBarWidth, double minCategoryGap)
{
double barWidth = 0;
do
{
double catSpace = xAxis.getCategorySpacing();
double avilableBarSpace = catSpace - (bc.getCategoryGap() + bc.getBarGap());
barWidth = (avilableBarSpace / bc.getData().size()) - bc.getBarGap();
if (barWidth > maxBarWidth)
{
avilableBarSpace = (maxBarWidth + bc.getBarGap()) * bc.getData().size();
bc.setCategoryGap(catSpace - avilableBarSpace - bc.getBarGap());
}
}
while (barWidth > maxBarWidth);
do
{
double catSpace = xAxis.getCategorySpacing();
double avilableBarSpace = catSpace - (minCategoryGap + bc.getBarGap());
barWidth = Math.min(maxBarWidth, (avilableBarSpace / bc.getData().size()) - bc.getBarGap());
avilableBarSpace = (barWidth + bc.getBarGap()) * bc.getData().size();
bc.setCategoryGap(catSpace - avilableBarSpace - bc.getBarGap());
}
while (barWidth < maxBarWidth && bc.getCategoryGap() > minCategoryGap);
}
public PieChart generatePieChart()
{
ObservableList<PieChart.Data> pieChartData = FXCollections.observableArrayList();
obj.stream().forEach((activeAgentGroup) ->
{
pieChartData.add(new PieChart.Data(activeAgentGroup.getDate(), activeAgentGroup.getDownloadTraffic()));
});
final PieChart chart = new PieChart(pieChartData);
chart.setTitle("Label");
return chart;
}
private void displayLabelForData(XYChart.Data<String, Number> data)
{
final Node node = data.getNode();
final Text dataText = new Text(data.getYValue().toString());
node.parentProperty().addListener(new ChangeListener<Parent>()
{
#Override
public void changed(ObservableValue<? extends Parent> ov, Parent oldParent, Parent parent)
{
Group parentGroup = (Group) parent;
parentGroup.getChildren().add(dataText);
}
});
node.boundsInParentProperty().addListener(new ChangeListener<Bounds>()
{
#Override
public void changed(ObservableValue<? extends Bounds> ov, Bounds oldBounds, Bounds bounds)
{
dataText.setLayoutX(
Math.round(
bounds.getMinX() + bounds.getWidth() / 2 - dataText.prefWidth(-1) / 2
)
);
dataText.setLayoutY(
Math.round(
bounds.getMinY() - dataText.prefHeight(-1) * 0.5
)
);
}
});
}
}
I ant to add circular progress bar during switch of the charts and loading of the data. Usually it takes 2-3 seconds to load data from the database, so I need a way to display progress bay because the charts are stacked.
Also is there any much easy way to implement the switching of the charts?
Short and sweet:
Use a BorderPane as parent container for your charts.
Use Bindings, Task.runningProperty() and BorderPane.centerProperty()
For example something like this:
myBorderPane.centerProperty().bind(
Bindings
.when(myLongTask.runningProperty())
.then(myProggressIndicator)
.otherwise(myChart));
With following code (JavaFX 8) I get 4 rectangles (Cards). The rectangles were displayed with 15px shift. Last card is on the top of the Deck. How can I take with the right mouse event another cards to the top?
Another words, how can I primaryStage rebuild?
package application;
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.EventHandler;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.scene.input.MouseButton;
import javafx.scene.input.MouseEvent;
import javafx.scene.paint.Color;
import javafx.scene.paint.ImagePattern;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
public class Main extends Application {
private static ObservableList<Rectangle> cardList = FXCollections.observableArrayList();
public static Rectangle getCard(int i) {
Image card = new Image("file:C:\\Workspace\\pic\\" + i + "_12.png");
Rectangle rect = new Rectangle(100 + i * 15, 120, 71, 96);
rect.setFill(new ImagePattern(card));
rect.setOnMousePressed(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent t) {
if (t.getButton().equals(MouseButton.SECONDARY)) {
rect.setStrokeWidth(2);
rect.setStroke(Color.YELLOW);
}
}
});
rect.setOnMouseReleased(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent t) {
if (t.getButton().equals(MouseButton.SECONDARY)) {
rect.setStrokeWidth(0);
}
}
});
return rect;
}
#Override
public void start(Stage primaryStage) {
primaryStage.setTitle("4 cards");
Group root = new Group();
Scene scene = new Scene(root, 300, 300);
for (int i = 0; i < 4; i++) {
cardList.add(getCard(i));
}
for (int i = 0; i < 4; i++) {
root.getChildren().addAll(cardList.get(i));
}
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}