Why the program gets the error in JavaFX? [duplicate] - javafx

This question already has an answer here:
How do I determine the correct path for FXML files, CSS files, Images, and other resources needed by my JavaFX Application?
(1 answer)
Closed 2 years ago.
I have spent the last 3 days trying to find an answer, watching videos and forum posts but no luck. Please take a look in those 4 pics. It seems that it only does it when the problem has image files.
import javafx.application.Application;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.layout.GridPane;
import javafx.stage.Stage;
import javafx.scene.image.ImageView;
import javafx.scene.image.Image;
public class Exercise14_02 extends Application {
#Override
public void start(Stage primaryStage) {
Image imageX = new Image("image/x.gif");
Image imageO = new Image("image/o.gif");
GridPane pane = new GridPane();
pane.setAlignment(Pos.CENTER);
pane.setHgap(5);
pane.setVgap(5);
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
int status = (int)(Math.random() * 3);
if (status == 0) {
pane.add(new ImageView(imageX), j, i);
} else if (status == 1) {
pane.add(new ImageView(imageO), j, i);
}
}
}
// Create a scene and place it in the stage
Scene scene = new Scene(pane);
primaryStage.setTitle("Exercise14_02"); // Set the stage title
primaryStage.setScene(scene); // Place the scene in the stage
primaryStage.show(); // Display the stage
}
public static void main(String[] args) {
launch(args);
}
}

try moving your images to 'resources' folder, create one if needed.
Image imagex = new Image(getClass().getResourceAsStream("/resources/your_image.jpg"));
or
check if you have included your resources folder in project.

Related

JavaFX Alert with multiple colors

I have a program that at some point (may) displays two warnings - one about errors - those are in red, and one about warnings - those are in orange.
I wonder however if there is a way - using css - to have just one warning with some text red and some text orange.
Here is an example of what I want to achieve (the two can be separated into "sections"):
RED ERROR1
RED ERROR2
RED ERROR3
ORANGE WARNING1
ORANGE WARNING2
I've seen some answers pointing to RichTextFX like this one, however I don't see (or don't know) how that could apply to generic Alerts. Is that even possible, without writing some custom ExpandedAlert class?
The Alert class inherits from Dialog, which provides a pretty rich API and allows arbitrarily complex scene graphs to be set via the content property.
If you just want static text with different colors, the simplest approach is probably to add labels to a VBox; though you could also use more complex structures such as TextFlow or the third-party RichTextFX mentioned in the question if you need.
A simple example is:
import java.util.Random;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.Button;
import javafx.scene.control.ButtonType;
import javafx.scene.control.Label;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class App extends Application {
private final Random rng = new Random();
private void showErrorAlert(Stage stage) {
Alert alert = new Alert(Alert.AlertType.ERROR);
int numErrors = 2 + rng.nextInt(3);
int numWarnings = 2 + rng.nextInt(3);
VBox errorList = new VBox();
for (int i = 1 ; i <= numErrors ; i++) {
Label label = new Label("Error "+i);
label.setStyle("-fx-text-fill: red; ");
errorList.getChildren().add(label);
}
for (int i = 1 ; i <= numWarnings ; i++) {
Label label = new Label("Warning "+i);
label.setStyle("-fx-text-fill: orange; ");
errorList.getChildren().add(label);
}
alert.getDialogPane().setContent(errorList);
alert.initOwner(stage);
alert.show();
}
#Override
public void start(Stage stage) {
Button showErrors = new Button("Show Errors");
showErrors.setOnAction(e -> showErrorAlert(stage));
BorderPane root = new BorderPane(showErrors);
Scene scene = new Scene(root, 400, 400);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch();
}
}
which gives this result:

Can't get images to show up, trying to display 5 random cards from directory file

I'm not sure what I'm doing wrong. My pane opens, but it is blank. I have the file (card) as a directory (image) in the src folder. I have tried writing this so many different way but always get the same result. I just need to make the images actually show up. I don't know how to get the card images to show up. Any help is greatly appreciated.
package Assignment;
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.FlowPane;
import javafx.stage.Stage;
import java.util.ArrayList;
import java.util.Collections;
public class Assignment extends Application {
#Override // Override the start method in the Application class
public void start(Stage primaryStage) {
// Initialize card deck
ArrayList<Integer> cards = getCards();
// Create a FlowPane
FlowPane pane = new FlowPane();
pane.setVgap(10);
pane.setHgap(10);
pane.setPadding(new Insets(15, 15, 15, 15));
for (int i = 0; i < 5; i++) {
pane.getChildren().add(new ImageView(new Image("file:image/card/" + cards.get(i) + ".png")));
}
// Create scene and place it in the stage
Scene scene = new Scene(pane,500, 300);
primaryStage.setTitle("Poker 1");
primaryStage.setScene(scene);
primaryStage.show();
}
private ArrayList<Integer> getCards() {
ArrayList<Integer> cards = new ArrayList<>();
for (int i = 0; i < 52; i++) {
cards.add(i + 1);
}
Collections.shuffle(cards);
return cards;
}
public static void main(String[] args) {
launch(args);
}
}
What directory are your cards images in?
Click 'edit configuration' on the run button drop down menu, then look at the "Working directory" entry. Ex. Mine was C:\Users\NAME\IdeaProjects\Test
Placing the cards in C:\Users\NAME\IdeaProjects\Test\image\cards[1-52].png made your code work for me as written.

Memory leak with FXCanvas

I'm working on Eclipse e4 RCP application where I have one SWT part. Using JavaFX interoperability with SWT I have added javafx.embed.swt.FXCanvas. After I create a javafx.scene.Scene with 50000 javafx.scene.control.Button and hook it to the canvas, application memory jumps to 1.5gb.
Problem starts when I close that part, application does not release a memory. When I open that part again, memory jumps to 2.something gb.
Part class:
import javax.annotation.PostConstruct;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import javafx.embed.swt.FXCanvas;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ScrollPane;
import javafx.scene.layout.Pane;
public class StressTestJavaFXPart
{
private Scene scene;
private FXCanvas canvas;
private final int columns = 100;
private final int rows = 500;
#PostConstruct
public void createComposite(final Composite parent)
{
parent.setLayout(new GridLayout(1, false));
canvas = new FXCanvas(parent, SWT.NONE);
GridDataFactory.fillDefaults().grab(true, true).span(0, 0).applyTo(canvas);
final Pane pane = new Pane();
for (int i = 0; i < columns ; i++)
{
for (int j = 0; j < rows ; j++)
{
final Button button = new Button(String.format("%s : %s", i, j));
pane.getChildren().add(button);
button.setLayoutX(100 * i);
button.setLayoutY(100 * j);
}
}
final ScrollPane sp = new ScrollPane(pane);
scene = new Scene(sp);
canvas.setScene(scene);
parent.addDisposeListener(new DisposeListener()
{
#Override
public void widgetDisposed(final DisposeEvent e)
{
canvas.dispose();
System.gc();
}
});
}
}
Any suggestions are very welcome! Thanks
I solved it using reflection:
parent.addDisposeListener(disposeEvent -> {
//release Pixel Buffer via Reflection -> prevents memory leak
try {
Field pixelBuffer = FXCanvas.class.getDeclaredField("pixelsBuf");
pixelBuffer.setAccessible(true);
pixelBuffer.set(this, null);
} catch (NoSuchFieldException | IllegalAccessException e) {
}
});
Worked well for me.

Creating TicTacToe in javafx

I am writing a TicTacToe program that displays a tic-tac-toe board that has the following qualities:
A cell may be X, O, or empty.
What to display at each cell is randomly decided upon startup of program.
Input the X's and O's as text instead of images.
In my program, I have the X's and O's as .gif files. I was wondering how the code would look when placing the X's and O's as text instead of images? Thanks in advance!
here is my code:
import javafx.application.Application;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.text.Text;
import javafx.scene.layout.GridPane;
import javafx.stage.Stage;
public class TicTacToe extends Application {
#Override
public void start(Stage primaryStage) {
GridPane pane = new GridPane();
pane.setAlignment(Pos.CENTER);
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
int random = (int)(Math.random() * 3);
if (random != 2) {
String text = (random > 0) ? "/image/x.gif" : "/image/o.gif";
pane.add(new ImageView(new Image(image)), j, i);
}
}
}
Scene scene = new Scene(pane, 150, 150);
primaryStage.setTitle("Tic Tac Toe");
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
Application.launch(args);
}
}
// Create a scene and place it in the stage
Scene scene = new Scene(pane);
primaryStage.setTitle("TicTacToe"); // Set the stage title
primaryStage.setScene(scene); // Place the scene in the stage
primaryStage.show(); // Display the stage
}
public static void main(String[] args) {
launch(args);
}
}
Replace "/image/x.gif" with "X" and "/image/o.gif" with "O" and instead of using an ImageView, use a Label and set the text of the label to the text variable then add it to your Pane

Centering an image in an ImageView

I am currently trying to center an image in an ImageView using JavaFX.
So I load the image in the view :
Image img = new Image("...");
imageView.setImage(img);
and let's suppose the image is huge (2000x3000) and not the ImageView (400x100)
The rendered image will be aligned on the left, and I would like to put in the center of the ImageView :
Is there anyway to perform that ?
So, after days of calculation, I managed to find a good way to do it.
I post it here in case of someone would like to achieve it.
I created a method that only needs access to the imageView :
public void centerImage() {
Image img = imageView.getImage();
if (img != null) {
double w = 0;
double h = 0;
double ratioX = imageView.getFitWidth() / img.getWidth();
double ratioY = imageView.getFitHeight() / img.getHeight();
double reducCoeff = 0;
if(ratioX >= ratioY) {
reducCoeff = ratioY;
} else {
reducCoeff = ratioX;
}
w = img.getWidth() * reducCoeff;
h = img.getHeight() * reducCoeff;
imageView.setX((imageView.getFitWidth() - w) / 2);
imageView.setY((imageView.getFitHeight() - h) / 2);
}
}
Here is an example code that might be a solution for your case:
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
public class Test extends Application {
#Override
public void start(Stage primaryStage) {
Image image = new Image("https://upload.wikimedia.org/wikipedia/commons/a/a7/Frankenstein's_monster_(Boris_Karloff).jpg");
ImageView imageView = new ImageView();
imageView.setImage(image);
imageView.setPreserveRatio(true);
imageView.setFitWidth(400);
imageView.setFitHeight(300);
BorderPane pane = new BorderPane();
pane.setPrefSize(400, 300);
pane.setCenter(imageView);
primaryStage.setScene(new Scene(pane));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
And the result:
Here's how I would do it
import javafx.geometry.Pos;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.HBox;
Image img = new Image("...");
imageView imgView = new imageView(img);
HBox hbxImg = new HBox();
hbxImg.setAlignment(Pos.CENTER);
hbxImg.getChildren().add(imgView);
That'll put an image in an empty HBox you can align to the horizontal center of the canvas.

Resources