So im new to javaFX and want to make a borderpane with some buttons on the left and a canvas to draw lines with mouse in center.. on line 49 and 55 i get an error saying "cannot find symbol, variable scene".. why is that?
Please ignore my buttons, they are just there for show. Any other mistakes or pointers I would love aswell!
package simplepaint;
import javafx.scene.canvas.Canvas;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.control.Button;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.geometry.Insets;
import javafx.scene.paint.Color;
public class SimplePaint extends Application {
Button but0, but1, but2, but3, but4, but5, but6;
#Override
public void start(Stage primaryStage) {
primaryStage.setTitle("Simple paint");
//Creates all buttons
but0 = new Button("0"); //Create button - Line
but1 = new Button("1"); //Create button - rectangle
but2 = new Button("2"); //Create button - circle
but3 = new Button("3"); //Create button - move object backwards
but4 = new Button("4"); //Create button - Move object foreward
but5 = new Button("5"); //Create button - Move object backwards(1 spot)
but6 = new Button("6"); //Create button - Move object foreward (1 spot)
//Gives all buttons functions
but0.setOnAction(e -> System.out.println("Bro 0!"));
but1.setOnAction(e -> System.out.println("Bro 1!"));
but2.setOnAction(e -> System.out.println("Bro 2!"));
but3.setOnAction(e -> System.out.println("Bro 3!"));
but4.setOnAction(e -> System.out.println("Bro 4!"));
but5.setOnAction(e -> System.out.println("Bro 5!"));
but6.setOnAction(e -> System.out.println("Bro 6!"));
Canvas canvas = new Canvas(750,450); //Making draw window
GraphicsContext gc;
gc = canvas.getGraphicsContext2D();
gc.setStroke(Color.BLACK);
gc.setLineWidth(1);
/*Line 49*/ scene.setOnMousePressed (e -> {
gc.beginPath();
gc.lineTo(e.getSceneX(), e.getSceneY());
gc.stroke();
});
/*Line 55*/ scene.setOnMouseDragged (e -> {
gc.lineTo(e.getSceneX(), e.getSceneY());
gc.stroke();
});
VBox buttons = new VBox(3);
buttons.setPadding(new Insets(50, 10, 10, 10));
buttons.getChildren().addAll(but0, but1, but2, but3, but4, but5, but6); //Adds all the buttons on VBox
BorderPane bp = new BorderPane();
bp.setLeft(buttons); //Placing buttons on left
bp.setCenter(canvas); //Placing draw box in center
Scene scene = new Scene(bp, 800, 500);
primaryStage.setScene(scene);
primaryStage.show();
} public static void main(String[] args) {
Application.launch(args);
}
}
Related
I am trying to create a game with JavaFX. I have created 2 stages, one is for the splashscreen, the second one is for the actual game itself. This is my first ever JavaFX program, i am a student learning JavaFX. The problem i am having is that when i hide the first stage and show the second one, the second stage stays blank for a few seconds and then continues to show all element(s). For now, there is only a gif showing in the stage with some music(which is not delayed in loading, because it is an instance variable). I don't want to create many instance variables for each of the elements i wish to put into the stage. Below is the code, where only the necessary code is shown to understand the problem:
import java.awt.Dimension;
import java.awt.Toolkit;
import java.io.File;
import javafx.animation.Animation;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.control.CheckBox;
import javafx.scene.control.Slider;
import javafx.scene.control.TextField;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.input.MouseEvent;
import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import javafx.stage.Stage;
import javafx.util.Duration;
public class Main extends Application {
Dimension window = Toolkit.getDefaultToolkit().getScreenSize();
private double screenWidth = window.getWidth();
private double screenHeight = window.getHeight();
private boolean fullscreen = false;
private boolean music = false;
private double value = 0;
private Group root, root2;
private Image start;
private Image startHover;
private ImageView startViewer;
private Stage stage;
private boolean firstWindowExists = true;
private CheckBox full;
private CheckBox sound;
private Slider slider;
private Image BG;
private ImageView BGView;
private String path = "bin/Audio/8_bit_march.mp3";
private Media media;
private MediaPlayer player;
public static void main(String[] args) {
launch();
}
private void run() {
Image title = new Image("Title.png", 300, 0, true, true);
ImageView titleView= new ImageView();
titleView.setX(200);
titleView.setY(10);
titleView.setImage(title);
add(titleView);
start = new Image("Start1.png", 200, 0, true, true);
startHover = new Image("Start_Hover1.png", 200, 0, true, true);
startViewer= new ImageView();
startViewer.setX(250);
startViewer.setY(300);
startViewer.setOnMouseEntered(mouseEnter);
startViewer.setOnMouseExited(mouseExit);
startViewer.setOnMouseReleased(mouseReleased);
startViewer.setImage(start);
add(startViewer);
if (!firstWindowExists) {//this code works
Image title2 = new Image("BG.gif", (screenWidth/1.25) + 4, (screenHeight/1.25)+4, false, true);
ImageView titleView2= new ImageView();
titleView2.setX(-2);
titleView2.setY(-2);
titleView2.setImage(title2);
add2(titleView2);
}
}
EventHandler<ActionEvent> event = new EventHandler<ActionEvent>() {
public void handle(ActionEvent e)
{
if (sound.isSelected()) { // the checkbox is checked to be enabled
slider.setVisible(true);
}
else {
slider.setVisible(false);
}
}
};
EventHandler<MouseEvent> mouseEnter = new EventHandler<MouseEvent>() {
public void handle(MouseEvent event) { // irrelevant for this problem
startViewer.setImage(startHover);
}
};
EventHandler<MouseEvent> mouseExit = new EventHandler<MouseEvent>() {
public void handle(MouseEvent event) {
startViewer.setImage(start);
}
};
EventHandler<MouseEvent> mouseReleased = new EventHandler<MouseEvent>() {
public void handle(MouseEvent event) {
stage.hide(); //hide first window
firstWindowExists = false;
Stage stage2 = new Stage(); // creating a new stage
root2 = new Group(); //creating new group
Scene scene2 = new Scene(root2, Color.WHITE);// creating a scene and adding the newly created Group
Canvas canvas2 = new Canvas(screenWidth/1.25, screenHeight/1.25); // creating a canvas for the screen
root2.getChildren().add(canvas2); // adding canvas to the group (window)
stage2.setTitle("Game"); // setting the title of the window
stage2.setScene(scene2); // Adds scene to the stage
stage2.setFullScreen(fullscreen);
stage2.show(); //after showing the screen here, it stays blank and then adds the title2 gif
stage2.centerOnScreen();
if (music) { //plays music
player.play();
player.setVolume(value);
player.setCycleCount(MediaPlayer.INDEFINITE);
}
run(); // runs the method with heavy lifting stuff
}
};
Timeline timeline = new Timeline(new KeyFrame(Duration.seconds(1), event -> {
}));
private void add(Node node) {
if (firstWindowExists) {
root.getChildren().add(node);
}
}
private void add2(Node node) {
root2.getChildren().add(node);
}
#Override
public void start(Stage stage) throws Exception { // main method which creates the first window
this.stage = stage;
stage.setTitle("Test GUI");
root = new Group();
Scene scene = new Scene(root, Color.DARKGRAY);
Canvas canvas = new Canvas(700, 350);
root.getChildren().add(canvas);
stage.setScene(scene);
stage.setResizable(false);
stage.show();
stage.centerOnScreen();
root.requestFocus();
run();
media = new Media(new File(path).toURI().toString());
player = new MediaPlayer(media);
}
}
I am using ControlsFX - HiddenSidesPane where i add some link(ToggleButtons) to be clicked for navigation.
The problem i have is whenever anything is clicked, the HiddenSiddesPane hides.
The desired behavior is when anything inside it is clicked it should not close/hide, unless cursor hovers out of it.
SSCCE to demonstrate undesired behavior
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.ListView;
import javafx.scene.control.TableView;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import org.controlsfx.control.HiddenSidesPane;
public class MyHiddenSidesPaneDemo extends Application{
public static void main(String[] args) { Application.launch(args); }
#Override
public void start(Stage primaryStage) throws Exception {
VBox root = new VBox();
TableView tv = new TableView();
HiddenSidesPane hiddenSidesPane = new HiddenSidesPane();
hiddenSidesPane.setContent(tv);
hiddenSidesPane.setLeft(new ListView());
root.getChildren().addAll(hiddenSidesPane);
primaryStage.setTitle("HiddenSidesPane Example Demo");
Scene scene = new Scene(root);
primaryStage.setScene(scene);
primaryStage.show();
}
}
Try the following:
ListView listView = new ListView();
hiddenSidesPane.setLeft(listView);
listView.setOnMouseEntered(e->hiddenSidesPane.setPinnedSide(Side.LEFT)); //Keep left side pinned
listView.setOnMouseExited(e->hiddenSidesPane.setPinnedSide(null)); //unpin when mouse exits
The circle should go back and forth but the start button is not starting it for some reason? When I ran the example file it worked and it looks exactly like mine so not sure why Mine isnt starting. Does anybody know why? Thanks
package projavafx.metronometransition.ui;
import javafx.animation.Animation;
import javafx.animation.Interpolator;
import javafx.animation.TranslateTransition;
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.HBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;
import javafx.util.Duration;
public class MetronomeTransitionMain extends Application{
Button startButton;
Button pauseButton;
Button resumeButton;
Button stopButton;
Circle circle;
public static void main(String[] args) { Application.launch(args);}
#Override
public void start(Stage stage) {
circle = new Circle(100, 50, 4, Color.BLUE);
TranslateTransition anim = new TranslateTransition(new Duration(1000.0), circle);
anim.setFromX(0);
anim.setToX(200);
anim.setAutoReverse(true);
anim.setCycleCount(Animation.INDEFINITE);
anim.setInterpolator(Interpolator.LINEAR);
startButton = new Button("start");
startButton.setOnAction(e -> anim.playFromStart());
pauseButton = new Button("pause");
startButton.setOnAction(e -> anim.pause());
resumeButton = new Button("resume");
resumeButton.setOnAction(e -> anim.play());
stopButton = new Button("stop");
stopButton.setOnAction(e -> anim.stop());
HBox commands = new HBox(10, startButton,
pauseButton,
resumeButton,
stopButton);
commands.setLayoutX(60);
commands.setLayoutY(420);
Group group = new Group(circle, commands);
Scene scene = new Scene(group, 400, 500);
startButton.disableProperty().bind(anim.statusProperty()
.isNotEqualTo(Animation.Status.STOPPED));
pauseButton.disableProperty().bind(anim.statusProperty()
.isNotEqualTo(Animation.Status.RUNNING));
resumeButton.disableProperty().bind(anim.statusProperty()
.isNotEqualTo(Animation.Status.PAUSED));
stopButton.disableProperty().bind(anim.statusProperty()
.isEqualTo(Animation.Status.STOPPED));
stage.setScene(scene);
stage.setTitle("Metronome using TranslateTransition");
stage.show();
}
}
I have undecorated non-fullscreen window, which I like to move outside screen boundaries when mouse leaves it's area, but do so smoothly. I found some JavaFX functionality to do so - Timeline, but KeyValue for that Timeline doesn't supports stage.xProperty - because this property is readonlyProperty. Is there way to move my window smoothly using JavaFX functions?
You can setup proxy properties that you manipulate via KeyValues in a Timeline. A listener on the proxy can modify the actual stage location.
import javafx.animation.*;
import javafx.application.*;
import javafx.beans.property.*;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.text.TextAlignment;
import javafx.stage.*;
import javafx.util.Duration;
public class StageSwiper extends Application {
private static final int W = 350;
private static final Duration DURATION = Duration.seconds(0.5);
#Override
public void start(Stage stage) throws Exception {
Label instructions = new Label(
"Window will slide off-screen when the mouse exits it.\n" +
"Click the window to close the application."
);
instructions.setTextAlignment(TextAlignment.CENTER);
final StackPane root = new StackPane(instructions);
root.setStyle("-fx-background-color: null;");
DoubleProperty stageX = new SimpleDoubleProperty();
stageX.addListener((observable, oldValue, newValue) -> {
if (newValue != null && newValue.doubleValue() != Double.NaN) {
stage.setX(newValue.doubleValue());
}
});
final Timeline slideLeft = new Timeline(
new KeyFrame(
DURATION,
new KeyValue(
stageX,
-W,
Interpolator.EASE_BOTH
)
),
new KeyFrame(
DURATION.multiply(2)
)
);
slideLeft.setOnFinished(event -> {
slideLeft.jumpTo(Duration.ZERO);
stage.centerOnScreen();
stageX.setValue(stage.getX());
});
root.setOnMouseClicked(event -> Platform.exit());
root.setOnMouseExited(event -> slideLeft.play());
stage.setScene(new Scene(root, W, 100, Color.BURLYWOOD));
stage.initStyle(StageStyle.UNDECORATED);
stage.show();
stage.centerOnScreen();
stageX.set(stage.getX());
}
public static void main(String[] args) {
launch(args);
}
}
Is it possible to change the default behaviour of a JavaFX TextArea, so that pressing Tab passes the focus to the next component?
While #ItachiUchiha solution works, as he states, it depends on the layout (box in his sample).
Based on this question, you can modify the default behavior of a TextArea, regardless of the layout.
But you will need to use for this private API, which may change at any time without notice.
In this sample Tab and Shitf+Tab will have the desired behavior, while Ctrl+Tab will insert "\t" on the text area.
#Override
public void start(Stage primaryStage) {
TextArea area = new TextArea();
area.addEventFilter(KeyEvent.KEY_PRESSED, (KeyEvent event) -> {
if (event.getCode() == KeyCode.TAB) {
TextAreaSkin skin = (TextAreaSkin) area.getSkin();
if (skin.getBehavior() instanceof TextAreaBehavior) {
TextAreaBehavior behavior = (TextAreaBehavior) skin.getBehavior();
if (event.isControlDown()) {
behavior.callAction("InsertTab");
} else if (event.isShiftDown()) {
behavior.callAction("TraversePrevious");
} else {
behavior.callAction("TraverseNext");
}
event.consume();
}
}
});
VBox root = new VBox(20, new Button("Button 1"), area, new Button("Button 2"));
Scene scene = new Scene(root, 400, 300);
primaryStage.setScene(scene);
primaryStage.show();
}
Well, you definitely can do this, but it depends on the Layout to which the TextArea is added to. I have created a simple example where a TextArea and a TextField are both added to a VBox. There is a keyEventHandler which monitors the keyPress event on the TextArea and sends the focus to the next child(if any)
import java.util.Iterator;
import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class TextAreaTabFocus extends Application {
#Override
public void start(Stage primaryStage) throws Exception {
VBox box = new VBox();
TextArea textArea = new TextArea();
TextField textField = new TextField();
box.getChildren().addAll(textArea, textField);
final EventHandler<KeyEvent> keyEventHandler =
keyEvent -> {
if (keyEvent.getCode() == KeyCode.TAB) {
Iterator<Node> itr = box.getChildren().iterator();
while(itr.hasNext()) {
if(itr.next() == keyEvent.getSource()) {
if(itr.hasNext()){
itr.next().requestFocus();
}
//If TextArea is the last child
else {
box.getChildren().get(0).requestFocus();
}
break;
}
}
keyEvent.consume();
}
};
textArea.setOnKeyPressed(keyEventHandler);
Scene scene = new Scene(box, 200, 200);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}