I am new to javafx and am trying to connect my class to my CSS file however when I use:
scene.getStylesheets().add("Viper.css");
I get the following warning:
Dec 08, 2016 9:12:54 PM com.sun.javafx.css.StyleManager loadStylesheetUnPrivileged
WARNING: Resource "Viper.css" not found.
But when I use:
scene.getStylesheets().add(getClass().getResource("/resources/CSS/Viper.css").toExternalForm());
I get an InvocationTargetException
Here is my entire class and I am positive that the filepath is correct. I am using NetBeans IDE.
package com.GUI;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Pane;
import javafx.scene.text.Font;
import javafx.scene.text.FontWeight;
import javafx.scene.text.Text;
import javafx.stage.Stage;
public class window extends Application{
#Override
public void start(Stage primaryStage) {
primaryStage.setTitle("OmegaBrain");
//Create Panes
Pane titlePane = new Pane();
GridPane grid = new GridPane();
grid.setAlignment(Pos.CENTER);
grid.setHgap(10);
grid.setVgap(10);
grid.setPadding(new Insets(25, 25, 25, 25));
Text sceneTitle = new Text("Welcome To OmegaBrain");
sceneTitle.setFont(Font.font("Helvetica", FontWeight.NORMAL, 20));
grid.add(sceneTitle, 0, 0, 4, 1);
Scene scene = new Scene(grid, 300, 275);
scene.getStylesheets().add("/resources/CSS/Viper.css");
primaryStage.setScene(scene);
primaryStage.show();
Button play = new Button("Play");
grid.add(play, 1, 1);
Button leaderboard = new Button("Leaderboard");
grid.add(leaderboard, 2, 1);
Button faq = new Button("FAQs");
grid.add(faq, 3, 1);
Button exit = new Button("Exit");
grid.add(exit, 4, 1);
play.setOnAction((ActionEvent e) -> {
System.out.println("The play button was clicked!");
});
}
public static void main(String[]args){
launch(args);
}
}
Assuming that your application is built with this hierarchy :
Application
->src
-->com/GUI/window.java
-->resources/CSS/Viper.css
Then this piece of code should work :
scene.getStylesheets().add(getClass().getResource("/resources/CSS/Viper.css").toExternalForm());
// or
scene.getStylesheets().add("/resources/CSS/Viper.css");
You can solve it with scene.getStylesheets().add("Package Name/Viper.css"));
Related
New to java and JavaFX so please bear with me
I need to do a presentation of 5 3d fruit models that show in a continuous loop, 15 seconds apart: fruit1 for 15 seconds then fruit2 for 15 seconds ad so on and so forth.. until fruit5 for 15 seconds and then back to fruit1 and continues until I hit the ESC key which should close the window.
I also understand that it's ideal to change the root group object that makes up the scene instead of changing the scene, so I changed that in my code
I understand that a timeline is needed in order to change something in the scene as it plays out, but I've tried with something similar to what this answer says but I don't get the logic of how to switch the root of the scene every 15seconds
UPDATE:
I gave up on the timeline option and I found the platform.run option as seen on this article which seems to work as I see the window updates iterating from the first fruit in the scenes array to second one but I'm not sure why it only runs once when I need it to run every 15 seconds which means that my scene switcher: nextSceneIndex() should go back and forth between 1 and 0.
UPDATE2:
I went back to the timeline suggestion and I implemented Sedrick's solution and it worked... I can't be happier :)
Here's my working code!
public void start(Stage stage) throws Exception {
BorderPane[] scenes = new BorderPane[]{createSceneApple(),createSceneCarrot(),createSceneTomato()};
Timeline tl = new Timeline();
tl.setCycleCount(Animation.INDEFINITE);
KeyFrame kf_fruit = new KeyFrame(Duration.seconds(10),
new EventHandler<ActionEvent>() {
public void handle(ActionEvent event) {
if (index==0){
root.getChildren().setAll(scenes[0]);
index = 1;
}else if(index==1){
root.getChildren().setAll(scenes[1]);
index = 2;
}else if(index==2){
root.getChildren().setAll(scenes[2]);
index = 0;
}
}
});
tl.getKeyFrames().add(kf_fruit);
tl.play();
Scene scene = new Scene(root, windowWidth, windowHeight);
stage.setScene(scene);
stage.show();
}
Maybe you can get some ideas from here. This uses the code from the link I posted above. Timeline is used to loop through a list of Shape and info about that shape.
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Line;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
import javafx.util.Duration;
/**
* JavaFX App
*/
public class App extends Application {
#Override
public void start(Stage stage) {
List<MyShape> shapes = new ArrayList();
shapes.add(new MyShape("Circle", "Shape.Circle", "More Circle Info", new Circle(25, Color.BLUE)));
shapes.add(new MyShape("Rectangle", "Shape.Rectangle", "More Rectangle Info", new Rectangle(100, 50, Color.RED)));
shapes.add(new MyShape("Line", "Shape.Line", "More Line Info", new Line(0, 0, 100, 100)));
TextField tf1 = new TextField();
TextField tf2 = new TextField();
TextArea ta1 = new TextArea();
VBox leftWindow = new VBox(tf1, tf2, ta1);
StackPane rightWindow = new StackPane(shapes.get(1).getShape());
AtomicInteger counter = new AtomicInteger();
Timeline timeline = new Timeline(new KeyFrame(Duration.seconds(1), new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
System.out.println(counter.get() % shapes.size());
MyShape currentShape = shapes.get(counter.getAndIncrement() % shapes.size());
tf1.setText(currentShape.getName());
tf2.setText(currentShape.getType());
ta1.setText(currentShape.getMoreInfo());
rightWindow.getChildren().set(0, currentShape.getShape());
}
}));
timeline.setCycleCount(Timeline.INDEFINITE);
timeline.play();
BorderPane root = new BorderPane();
root.setLeft(new StackPane(leftWindow));
root.setRight(rightWindow);
var scene = new Scene(root, 640, 480);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch();
}
}
Update:
If you only have two scenes, that simplifies some things. You basically need to set the initial view. You then need to switch out the view currently showing every two seconds. (I used two seconds so that you can see the views before they are switched out). I created my own version of createSceneCarrot and createSceneApple since I don't know your implementation.
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.scene.Scene;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
import javafx.util.Duration;
/**
* JavaFX App
*/
public class App extends Application {
#Override
public void start(Stage stage) {
BorderPane[] scenes = new BorderPane[]{createSceneApple(),createSceneCarrot()};
StackPane root = new StackPane(scenes[0]);//Set initial view;
Timeline timeline = new Timeline(new KeyFrame(Duration.seconds(2), (ActionEvent event) -> {
if(root.getChildren().get(0).equals(scenes[0]))//If the first scene is loaded, load the second scene.
{
root.getChildren().set(0, scenes[1]);
}
else
{
root.getChildren().set(0, scenes[0]);
}
}));
timeline.setCycleCount(Timeline.INDEFINITE);
timeline.play();
var scene = new Scene(root, 640, 640);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch();
}
public BorderPane createSceneApple()
{
BorderPane borderPane = new BorderPane();
TextField tf1 = new TextField("Rectangle 1");
TextField tf2 = new TextField("Rectangle Color: Blue");
TextArea ta1 = new TextArea("20x40");
VBox leftWindow = new VBox(tf1, tf2, ta1);
borderPane.setLeft(leftWindow);
StackPane rightWindow = new StackPane(new Rectangle(20, 40, Color.BLUE));
borderPane.setRight(rightWindow);
return borderPane;
}
public BorderPane createSceneCarrot()
{
BorderPane borderPane = new BorderPane();
TextField tf1 = new TextField("Circle 1");
TextField tf2 = new TextField("Circle Color: Blue");
TextArea ta1 = new TextArea("Radius: 50");
VBox leftWindow = new VBox(tf1, tf2, ta1);
borderPane.setLeft(leftWindow);
StackPane rightWindow = new StackPane(new Circle(50, Color.RED));
borderPane.setRight(rightWindow);
return borderPane;
}
}
I'm trying to create a cancel button, which looks something like this:
For the cross I'm currently using the letter 'x'.
Now I'm trying to reduce the empty space in the button, but I can't find a way to get rid of the vertical space.
Currently I have something like this:
package test;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Priority;
import javafx.scene.layout.Region;
import javafx.stage.Stage;
public class CancelButtonTestApplication extends Application {
#Override
public void start(Stage primaryStage) {
GridPane gridPane = new GridPane();
Label someLabel = new Label("Some Label:");
Button cancelButton = new Button("x");
cancelButton.setStyle("-fx-padding: 0.083333em 0.083333em 0.083333em 0.083333em;"); /* 1 1 1 1 */
cancelButton.setMaxHeight(Region.USE_PREF_SIZE);
someLabel.setLabelFor(cancelButton);
gridPane.add(someLabel, 0, 0);
gridPane.add(cancelButton, 1, 0);
gridPane.setHgap(5.0d);
GridPane.setVgrow(cancelButton, Priority.NEVER);
GridPane.setHgrow(cancelButton, Priority.NEVER);
Scene scene = new Scene(gridPane, 200, 50);
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}
It looks like this:
Not sure why are you not using Insets?
I did cancelButton.setPadding(new Insets(-5,0,-2,0)); and then I was able to remove the top/bottom space (that is available for Captial X). With capital X, I meant that if you will use X instead of x, you won't need any special padding but just Insets.EMPTY will do.
or to keep it dynamic you can even try FontMetrics
FontMetrics metrics = Toolkit.getToolkit().getFontLoader().getFontMetrics(cancelButton.getFont());
cancelButton.setPadding(new Insets(-metrics.getDescent()*1.8, 0, -metrics.getDescent(), 0));
this code shall got after scene.show() to get the correct matrix.
Full code:
package test;
import com.sun.javafx.tk.FontMetrics;
import com.sun.javafx.tk.Toolkit;
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Priority;
import javafx.scene.layout.Region;
import javafx.stage.Stage;
public class CloseButtonTestApplication extends Application {
#Override
public void start(Stage primaryStage) {
GridPane gridPane = new GridPane();
Label someLabel = new Label("Some Label:");
Button cancelButton = new Button("x");
//cancelButton.setStyle("-fx-padding: 0.083333em 0.083333em 0.083333em 0.083333em;"); /* 1 1 1 1 */
cancelButton.setMaxHeight(Region.USE_PREF_SIZE);
//cancelButton.setPadding(new Insets(0,0,0,0));
someLabel.setLabelFor(cancelButton);
Button cancelButton2 = new Button("X");
//cancelButton.setStyle("-fx-padding: 0.083333em 0.083333em 0.083333em 0.083333em;"); /* 1 1 1 1 */
cancelButton2.setMaxHeight(Region.USE_PREF_SIZE);
cancelButton2.setPadding(new Insets(0,0,0,0));
someLabel.setLabelFor(cancelButton);
gridPane.add(someLabel, 0, 0);
gridPane.add(cancelButton, 1, 0);
gridPane.add(cancelButton2, 2, 0);
gridPane.setHgap(5.0d);
GridPane.setVgrow(cancelButton, Priority.NEVER);
GridPane.setHgrow(cancelButton, Priority.NEVER);
Scene scene = new Scene(gridPane, 200, 50);
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
FontMetrics metrics = Toolkit.getToolkit().getFontLoader().getFontMetrics(cancelButton.getFont());
cancelButton.setPadding(new Insets(-metrics.getDescent()*1.8, 0, -metrics.getDescent(), 0));
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}
when i start the application, TitledPane does not show the GridPane I have added. Surprisingly it's visible the moment i increase/decrease the window width. where am i missing?
Here is the Complete Code:
package com.ct.bic.comparator;
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Accordion;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.PasswordField;
import javafx.scene.control.TextField;
import javafx.scene.control.TitledPane;
import javafx.scene.layout.GridPane;
import javafx.scene.text.Font;
import javafx.scene.text.FontWeight;
import javafx.stage.Stage;
public class Comparator extends Application {
#Override
public void start(Stage stage) {
GridPane dbGrid = new GridPane();
dbGrid.setId("dbGrid");
dbGrid.setAlignment(Pos.TOP_LEFT);
dbGrid.setHgap(10);
dbGrid.setVgap(10);
dbGrid.setPadding(new Insets(25, 25, 25, 25));
Label dbConnection = new Label("Database Configuration");
dbConnection.setId("dbConnection");
dbConnection.setFont(Font.font("Tahoma", FontWeight.NORMAL, 20));
dbGrid.add(dbConnection, 0, 0, 2, 1);
Label server = new Label("Server");
server.setId("server");
dbGrid.add(server, 0, 1);
TextField serverText = new TextField();
serverText.setId("serverText");
dbGrid.add(serverText, 1, 1);
Label database = new Label("Database");
database.setId("database");
dbGrid.add(database, 0, 2);
TextField databaseText = new TextField();
databaseText.setId("databaseText");
dbGrid.add(databaseText, 1, 2);
Label user = new Label("User");
user.setId("user");
dbGrid.add(user, 0, 3);
TextField userText = new TextField();
userText.setId("userText");
dbGrid.add(userText, 1, 3);
Label password = new Label("Password");
password.setId("password");
dbGrid.add(password, 0, 4);
PasswordField passwordText = new PasswordField();
passwordText.setId("passwordText");
dbGrid.add(passwordText, 1, 4);
dbGrid.setId("passwordText");
/*GridPane dbGrid = DatabaseInputGrid.getDatabaseGrid();*/
TitledPane tp = new TitledPane("Database Configuration", dbGrid);
Scene scene = new Scene(tp, 500,500);
stage.setScene(scene);
stage.setTitle("Bic-Java Output Comparator Pro");
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
I don't know the exact reason why, but it seems TitledPane is not resized if used as root for the Scene.
I tried something like this:
VBox vbox = new VBox();
vbox.getChildren().add(tp);
Scene scene = new Scene(vbox, 500,500);
Then everything works as expected.
Edit:
I have found this here:
Do not explicitly set the minimal, maximum, or preferred height of a
titled pane, as this may lead to unexpected behavior when the titled
pane is opened or closed.
So my guess is, when you set your TitledPane as root for the scene, it will try to set the preferred height, that leads to the mentioned "unexpected behaviour".
Despite there being numerous versions of this question, it still happens to come up with no single correct or straight forward answer.
I have the same problem and cannot execute my project.
I have my file on my desktop and it is called
login.java
I have run
javac Login.java
and now have two class files named Login$1.class and Login.class.
I get the error Could not find or load main class Login.java.
Please for the love of god can somebody answer this in a methodical way for java newbie.
I will happily follow and let you know what happens with each step.
Kind regards.
Here is the code
package login;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.PasswordField;
import javafx.scene.control.TextField;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;
import javafx.scene.text.FontWeight;
import javafx.scene.text.Text;
import javafx.stage.Stage;
public class Login extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) {
primaryStage.setTitle("JavaFX Welcome");
GridPane grid = new GridPane();
grid.setAlignment(Pos.CENTER);
grid.setHgap(10);
grid.setVgap(10);
grid.setPadding(new Insets(25, 25, 25, 25));
Text scenetitle = new Text("Welcome");
scenetitle.setFont(Font.font("Tahoma", FontWeight.NORMAL, 20));
grid.add(scenetitle, 0, 0, 2, 1);
Label userName = new Label("User Name:");
grid.add(userName, 0, 1);
TextField userTextField = new TextField();
grid.add(userTextField, 1, 1);
Label pw = new Label("Password:");
grid.add(pw, 0, 2);
PasswordField pwBox = new PasswordField();
grid.add(pwBox, 1, 2);
Button btn = new Button("Sign in");
HBox hbBtn = new HBox(10);
hbBtn.setAlignment(Pos.BOTTOM_RIGHT);
hbBtn.getChildren().add(btn);
grid.add(hbBtn, 1, 4);
final Text actiontarget = new Text();
grid.add(actiontarget, 1, 6);
btn.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent e) {
actiontarget.setFill(Color.FIREBRICK);
actiontarget.setText("Sign in button pressed");
}
});
Scene scene = new Scene(grid, 300, 275);
primaryStage.setScene(scene);
primaryStage.show();
}
}
I run
javac Login.java
Which works fine. Then I run
java login
I have also tried
java Login
With an Uppercase 'L' but still get
Error: Could not find or load main class login
You need to remove the package line, or put your file in a directory named login.
I made a simple file as so:
public class Login {
public static void main(String[] args) {
System.out.println("Ran.");
}
}
I then ran the following which works:
javac Login.java
java Login
I also made it work by creating a directory login/ with the package login:
login/Login.java contents are:
package login;
public class Login {
public static void main(String[] args) {
System.out.println("Ran.");
}
}
Then ran:
mkdir login
vi login/Login.java
javac login/Login.java
java login.Login
Works for me.
Edit:
As long as you have JavaFX, the same structure will make your code work. There is nothing unique about JavaFX that will affect your compilation. Your issue is just a directory structure + compilation issue.
You should probably rename your "login.java" file to "Login.java", and since this is in the package "login", you need to go up one directory, and run
java login.Login
EDIT: You mentioned this file is on your desktop, you need to put it in a folder named "login" since this file is in the login package
Okay, I am not sure if I am asking this in the right place but I am hoping someone here can help me. So, I am a beginner at Java and I am trying to make a JavaFX application but my Layout 1 "getChildren.addAll(label1, button1);" is being labeled as an error. That error is:
Cannot resolve method 'addAll(java.awt.Label, javafx.scene.control.Button)'
Any advice or help toward the problem is greatly appreciated. Thank You, if you read this.
package sample;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import java.awt.*;
public class Main extends Application {
Stage window;
Scene scene1, scene2;
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) {
window = primaryStage;
//Button 1
Label label1 = new Label("Welcome to the first scene!");
Button button1 = new Button("Go to scene 2");
button1.setOnAction(e -> window.setScene(scene2));
//Layout 1 - children laid out in vertical column
VBox layout1 = new VBox(20);
layout1.getChildren().addAll(label1, button1);
scene1 = new Scene(layout1, 200, 200);
//Button 2
Button button2 = new Button("Back to Scene 1");
button2.setOnAction(e -> window.setScene(scene1));
//Layout 2
StackPane layout2 = new StackPane();
layout2.getChildren().add(button2);
scene2 = new Scene(layout2, 450, 500);
window.setScene(scene1);
window.setTitle("The Title");
window.show();
}
}
Just make sure you don't import any classes from java.awt.*.
In your exception, it already says you are using java.awt.Label. You need the JavaFX version:
import javafx.scene.control.Label;