I've a "driver" file and a source file for the project I'm working on right now. In my driver file I add an EventHandle to me stage.
stage.addEventHandler(KeyEvent.KEY_TYPED, shape.getKeyHandler());
Now in my source file, Im try to define the function "getKeyHandler" in my source file. I've created a new EventHandler inside of the function. And went about creating a an event handler that takes in whatever key you press (R, G or B) and changes the circle/square on screen to its corresponding color. (G = Green, etc.)
The problem I'm running into is I'm not sure how to go about setting up a EventHandler that takes (KeyEvent.KEY_CLICKED). My two other EventHandlers were never called in the driver file, so I was able to this.addEventHandler to start off, now I'm in a different boat. Could someone push me in the correct direction.
Source File:
import javafx.application.Application;
import javafx.scene.Group;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
import javafx.scene.input.*;
import javafx.geometry.Point2D;
public class Multishape extends Group {
//Declaring variables here gives them greater scope
private Rectangle rectangle;
private Circle circle;
private Point2D prev;
public Multishape (double x, double y, double len){
rectangle = new Rectangle((len*2), (len*2), Color.RED);
rectangle.setX(x-len);
rectangle.setY(y-len);
rectangle.setStroke(Color.BLACK);
rectangle.setStrokeWidth(1);
circle = new Circle(len, Color.BLUE);
circle.setCenterX(x);
circle.setCenterY(y);
circle.setStroke(Color.BLACK);
circle.setStrokeWidth(1);
this.getChildren().add(rectangle);
this.addEventHandler(MouseEvent.MOUSE_CLICKED, (MouseEvent me) ->
{
if(me.getButton() == MouseButton.PRIMARY)
{
if(this.getChildren().get(0).equals(rectangle))
{
this.getChildren().set(0, circle);
}
else
{
this.getChildren().set(0, rectangle);
}
}
});
prev = new Point2D(320, 240);
this.addEventHandler(MouseEvent.MOUSE_DRAGGED, (MouseEvent me) ->
{
if(me.getButton() == MouseButton.SECONDARY)
{
if(this.getChildren().get(0).equals(rectangle))
{
rectangle.setX(prev.getX()-len);
rectangle.setY(prev.getY()-len);
circle.setCenterX(prev.getX());
circle.setCenterY(prev.getY());
}
else
{
circle.setCenterX(prev.getX());
circle.setCenterY(prev.getY());
rectangle.setX(prev.getX()-len);
rectangle.setY(prev.getY()-len);
}
}
prev = new Point2D(me.getX(), me.getY());
});
}
public EventHandler<KeyEvent> getKeyHandler(){
EventHandler<KeyEvent> keyPressHandler = new
EventHandler<KeyEvent>(){
#Override
public void handle(KeyEvent event){
if(event.getCode() == KeyCode.R){
circle.setFill(Color.RED);
rectangle.setFill(Color.RED);
}
if(event.getCode() == KeyCode.G){
circle.setFill(Color.GREEN);
rectangle.setFill(Color.GREEN);
}
if(event.getCode() == KeyCode.B){
circle.setFill(Color.BLUE);
rectangle.setFill(Color.BLUE);
}
}
};
return keyPressHandler;
}
}
Driver File:
import javafx.application.Application;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.Group;
import javafx.scene.input.KeyEvent;
import javafx.event.EventHandler;
public class MultishapeDriver extends Application
{
public static void main(String[] args)
{
launch(args);
}
public void start(Stage stage)
{
stage.setTitle("Multishape lab");
Group root = new Group();
Multishape shape = new Multishape(320, 240, 40);
root.getChildren().add(shape);
stage.addEventHandler(KeyEvent.KEY_TYPED,
shape.getKeyHandler());
stage.setScene(new Scene(root, 640, 480));
stage.show();
}
}
The KeyEvent.code property is undefined for KEY_TYPED events. You either need to use the character property
Color color = null;
switch(event.getCharacter().toLowerCase()) {
case "r":
color = Color.RED;
break;
case "g":
color = Color.LIME; // or green, but lime is #00ff00
break;
case "b":
color = Color.BLUE;
break;
default:
return;
}
circle.setFill(color);
rectangle.setFill(color);
or use a different event type, e.g. KEY_PRESSED
stage.addEventHandler(KeyEvent.KEY_PRESSED, shape.getKeyHandler());
Related
whenever I try to full screen my application, it doesn't scale. I've made multiple copies of this application trying different methods but none seem to work right.
First attempt: Application was a Parent, it would scale the background but the elements inside wouldn't scale to screen size.
As an update: here is the actual Parent that was made. The layout is the original one I wrote and has no issues when it's windowed. It has a preset WIDTH and HEIGHT but when full screened, The first example picture is what it looks like where the WIDTH of the the TextField doesn't update (since it's preset and not updating to the highest WIDTH of the screen it's running on). There are two parts to this that CAN be fixed when only one is fixed. The displayed Text has a set wrapping length of the console, though it is set by using WIDTH.
Here's what the console looks like when it's windowed:
If I could find a way to change the WIDTH, I'm thinking this can be fixed for both the TextField and the setWrappingWidth().
package application.console;
import application.areas.startingArea.SA;
import application.areas.vanguardForest.VFCmds;
import application.areas.vanguardForest.VFNavi;
import application.areas.vanguardForest.VFPkups;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.scene.Parent;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.ScrollPane.ScrollBarPolicy;
import javafx.scene.control.TextField;
import javafx.scene.layout.Background;
import javafx.scene.layout.BackgroundFill;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.scene.layout.Region;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
public class Ce extends Region {
public static boolean fullscreen = false;
public static double WIDTH = 990;
// 990;
// Screen.getPrimary().getBounds().getMaxX();
public static double HEIGHT = 525;
// 525;
// Screen.getPrimary().getBounds().getMaxY();
public static Font Cinzel = (Font.loadFont("file:fonts/static/Cinzel-Medium.ttf", 16));
public static VBox console = new VBox(2);
public static TextField input = new TextField();
public static ScrollPane scroll = new ScrollPane();
public static BorderPane root = new BorderPane();
public static String s;
public static Parent Window() {
root.setMinSize(WIDTH, (HEIGHT - input.getHeight()));
root.setStyle("-fx-background-color: #232323;");
scroll.setContent(console);
root.setCenter(scroll);
scroll.setStyle("-fx-background: #232323;"
+ "-fx-background-color: transparent;"
+ "-fx-border-color: #232323;"
+ "-fx-focus-color: #232323;"
);
scroll.setHbarPolicy(ScrollBarPolicy.NEVER);
scroll.setVbarPolicy(ScrollBarPolicy.NEVER);
scroll.setBackground(new Background(new BackgroundFill(Color.TRANSPARENT, null, null)));
console.setStyle("-fx-background-color: #232323;"
+ "-fx-focus-color: #232323;");
console.heightProperty().addListener(new ChangeListener<Object>() {
#Override
public void changed(ObservableValue<?> observable, Object oldValue, Object newValue) {
scroll.setVvalue((Double)newValue);
}
});
HBox hbox = new HBox();
hbox.setPrefSize(WIDTH, 16);
root.setBottom(hbox);
Text carrot = new Text(" >");
carrot.setFont(Font.loadFont("file:fonts/static/Cinzel-Medium.ttf", 26));
carrot.setFill(Color.WHITE);
input.setStyle("-fx-background-color: transparent;"
+ "-fx-text-fill: #FFFFFF;"
+ "-fx-highlight-fill: #FFFFFF;"
+ "-fx-highlight-text-fill: #232323;"
// + "-fx-border-color: #FFFFFF;"
// + "-fx-border-width: .5;"
);
input.setFont(Cinzel);
input.setMinWidth(console.getWidth());
input.setOnAction(e -> {
String s = (input.getText()).stripTrailing();
input.clear();
});
Pane pane = new Pane();
root.getChildren().add(pane);
hbox.getChildren().addAll(carrot, input);
return root;
}
This isn't the main issue as I've stated, once getting the scaled width for the TextField the process of for setWrappingWidth() for displaying the text should be the if a solution is found, here's how it goes:
#SuppressWarnings("static-access")
public void print(String s, Color c) {
Ce Ce = new Ce();
HBox text1 = new HBox();
text1.setMinWidth(Ce.WIDTH);
text1.setMaxWidth(Ce.WIDTH);
Text tCarrot = new Text(" > ");
tCarrot.setFont(Ce.Cinzel);
tCarrot.setFill(c);
Text text2 = new Text();
final IntegerProperty i = new SimpleIntegerProperty(0);
Timeline tl = new Timeline();
KeyFrame kf = new KeyFrame(
Duration.seconds(textSpeed(fastText)),
e1 -> {
if(i.get() > s.length()) {
tl.stop();
} else {
text2.setText(s.substring(0, i.get()));
i.set(i.get() + 1);
}
});
tl.getKeyFrames().add(kf);
tl.setCycleCount(Animation.INDEFINITE);
tl.play();
text2.setFill(c);
text2.setFont(Ce.Cinzel);
text2.setWrappingWidth(Ce.WIDTH - 40);
text1.getChildren().addAll(tCarrot, text2);
Ce.console.getChildren().add(text1);
Ce.console.setMargin(text1, new Insets(5, 0, 0, 3));
}
Lastly, the HEIGHT of the VBox for the displayed Text works just as intended, it's just the setting/updating the WIDTH to set it to the size of the window whether Windowed of Full screened that is the main issue here.
Try this app. It will not be exactly what you want but may provide some useful help for you if you study it, if not just ignore it, tears can keep you blind, and sometimes, that is ok.
The implementation follows the suggestions you have received in the comments on your questions which together explain what is being done and why, so I won't provide much commentary on the solution here.
Type text in the input bar, press enter and it will appear in the listview for the console log. Use the Toggle full-screen button to toggle full-screen mode on or off.
Console.java
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Pos;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.scene.text.Text;
import javafx.stage.Stage;
public class Console extends VBox {
private final ObservableList<String> consoleLog = FXCollections.observableArrayList();
private final ListView<String> logView = new ListView<>(consoleLog);
public Console(Stage stage) {
VBox.setVgrow(logView, Priority.ALWAYS);
HBox ribbon = createRibbon(
createFullScreenToggle(stage)
);
ribbon.setMinHeight(HBox.USE_PREF_SIZE);
getChildren().addAll(
ribbon,
logView
);
}
private ToggleButton createFullScreenToggle(Stage stage) {
ToggleButton fullScreenToggle = new ToggleButton("Toggle full screen");
fullScreenToggle.setOnAction(e ->
stage.setFullScreen(
fullScreenToggle.isSelected()
)
);
return fullScreenToggle;
}
private HBox createRibbon(ToggleButton fullscreenToggle) {
Text prompt = new Text(">");
TextField input = new TextField();
input.setOnAction(e -> {
consoleLog.add(0, input.getText());
logView.scrollTo(0);
input.clear();
});
HBox.setHgrow(input, Priority.ALWAYS);
HBox ribbon = new HBox(10,
prompt,
input,
fullscreenToggle
);
ribbon.setAlignment(Pos.BASELINE_LEFT);
return ribbon;
}
public ObservableList<String> getConsoleLog() {
return consoleLog;
}
}
ConsoleApplication.java
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class ConsoleApplication extends Application {
#Override
public void start(Stage stage) {
Console console = new Console(stage);
console.getConsoleLog().addAll(
TEXT.lines().toList()
);
stage.setScene(
new Scene(
console
)
);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
private static final String TEXT = """
W. Shakespeare - Sonnet 148
O me, what eyes hath Love put in my head,
Which have no correspondence with true sight!
Or, if the have, where is my judgement fled,
That censures falsely what they see aright?
If that be fair whereon my false eyes dote,
What means the world to say it is not so?
If it be not, then love doth well denote
Love’s eye is not so true as all men’s ‘No.’
How can it? O, how can Love’s eye be true,
That is so vex’d with watching and with tears?
No marvel then, though I mistake my view;
The sun itself sees not till heaven clears.
O cunning Love! with tears thou keep’st me blind.
Lest eyes well-seeing thy foul faults should find.
""";
}
If you want to increase the nodes height/width according to the viewport, then this's not the best practice, because every user will have the same font size at the end. What you can do is to make the font resizable by either GUI buttons or keyboard/mouse keys.
Here is a modification on your code, that will allow users to use ctrl + mouse wheel to increase/decrease the font (like any browser or terminal):
import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.beans.binding.ObjectBinding;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.TextField;
import javafx.scene.input.ScrollEvent;
import javafx.scene.layout.*;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import javafx.stage.Stage;
public class ConsoleTest extends Application {
#Override
public void start(Stage stage) {
Scene scene = new Scene(new GameWindow().Console(), 600, 600);
stage.setTitle("Console");
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch();
}
}
class GameWindow {
public static Console c = new Console();
public Parent Console() {
for (int i = 0; i < 100; i++) c.addText(new Text("Test" + i));
return c;
}
}
class Console extends BorderPane {
private final SimpleDoubleProperty fontSize = new SimpleDoubleProperty(20);
private final ObjectBinding<Font> fontBinding = Bindings.createObjectBinding(() -> Font.font(fontSize.get()), fontSize);
private final VBox console;
public Console() {
console = new VBox();
console.setBackground(new Background(new BackgroundFill(Color.BLACK, CornerRadii.EMPTY, Insets.EMPTY)));
ScrollPane scroll = new ScrollPane(console);
scroll.setHbarPolicy(ScrollPane.ScrollBarPolicy.NEVER);
scroll.setVbarPolicy(ScrollPane.ScrollBarPolicy.NEVER);
scroll.setFitToHeight(true);
scroll.setFitToWidth(true);
scroll.setPadding(Insets.EMPTY);
Text caret = new Text(" >");
caret.fontProperty().bind(fontBinding);
caret.setFill(Color.WHITE);
TextField input = new TextField();
input.setStyle("-fx-background-color: transparent;" + "-fx-text-fill: #FFFFFF;" + "-fx-highlight-fill: #FFFFFF;" + "-fx-highlight-text-fill: #232323;");
input.fontProperty().bind(fontBinding);
HBox inputBar = new HBox(2, caret, input);
inputBar.setStyle("-fx-background-color: #232323;");
inputBar.setAlignment(Pos.CENTER_LEFT);
setCenter(scroll);
setBottom(inputBar);
EventHandler<ScrollEvent> scrollEvent = e -> {
if (e.isControlDown()) {
if (e.getDeltaY() > 0) {
fontSize.set(fontSize.doubleValue() + 2);
} else {
double old;
fontSize.set((old = fontSize.doubleValue()) < 10 ? old : old - 2);
}
e.consume();
}
};
inputBar.setOnScroll(scrollEvent);
console.setOnScroll(scrollEvent);
}
public void addText(Text text) {
text.fontProperty().bind(fontBinding);
text.setFill(Color.WHITE);
console.getChildren().add(text);
}
}
So, using JAVAfx, which I painfully downloaded, I need to be able to move this ball, but not let it leave the bounds. Right now, I have it all set up, it just leaves the area. What am i doing wrong? Any tutors don't know anything about JavaFX, so I'm having trouble getting past this. Right now I tried to work it out, but keep getting this error Cannot Make a Static Reference to Bound
'''
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;
import javafx.geometry.Bounds;
public class MoveBall extends Application {
// create buttons
Button left = new Button();
Button right = new Button();
Button up = new Button();
Button down = new Button();
Circle ball = new Circle(30, 30, 30);
// action event class
EventHandler<ActionEvent> event = new EventHandler<ActionEvent>() {
// handle them
#Override
public void handle(ActionEvent event) {
// movement of ball
if (event.getSource().equals(left) && ball.getLayoutX() >= (Bounds.getMaxX() + ball.getRadius())) {
ball.setCenterX(ball.getCenterX() - 5);
}
if (event.getSource().equals(right)) {
ball.setCenterX(ball.getCenterX() + 5);
}
if (event.getSource().equals(up)) {
ball.setCenterY(ball.getCenterY() - 5);
}
if (event.getSource().equals(down) && ball.getCenterY() < 400)) {
ball.setCenterY(ball.getCenterY() + 5);
}
}
};
// main method
public static void main(String[] args) {
Application.launch(args);
}
#Override
public void start(Stage primaryStage) {
primaryStage.setTitle("Ball Movement");
ball.setStroke(Color.BLACK);
ball.setFill(null);
// button location
left.setLayoutX(100);
left.setLayoutY(210);
left.setText("Left");
// button event
left.setOnAction(event);
// similar for all button
right.setLayoutX(150);
right.setLayoutY(210);
right.setText("Right");
right.setOnAction(event);
// button location
up.setLayoutX(200);
up.setLayoutY(210);
up.setText("Up");
// button event
up.setOnAction(event);
// similar for all button
down.setLayoutX(250);
down.setLayoutY(210);
down.setText("Down");
down.setOnAction(event);
Group root = new Group();
// add to a group
root.getChildren().add(left);
root.getChildren().add(right);
root.getChildren().add(up);
root.getChildren().add(down);
root.getChildren().add(ball);
primaryStage.setScene(new Scene(root, 400, 250, Color.WHITE));
// show the scene
primaryStage.show();
}
}
'''
Actually I am making an application which allows user to crop an image an then gives functionality of free-hand drawing and to also to draw different shapes. I have achieved functionality of cropping and drawing shapes like line etc. But I am facing some problems in free-hand drawing.
I have added my image on "HBox" and cropped that image through "Rectangle" in JavaFX class which is added on "Group". And all these are added on "Pane" class. Now for free-hand drawing, I am using "Canvas". Where to add canvas, whether on "HBox" or "Group" or "Pane" class. And Canvas is only initialized on clicking pencil button. I have added single functions for Mouse-Events and applied if-checks for different functionalities in those functions.
basically how to draw pencil on image or how to add lineTo on group.
Can someone please help me in solving my problem??
`
package application;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import javax.imageio.ImageIO;
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Point2D;
import javafx.scene.Cursor;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.control.Button;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.image.WritableImage;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Line;
import javafx.scene.shape.LineTo;
import javafx.scene.shape.Rectangle;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
public class Main extends Application {
int dragStatus = 0;
double startingPointX;
double startingPointY;
double currentEndingPointX;
double currentEndingPointY;
BufferedImage bufferedImage;
Robot robot;
ImageView imageView;
Button pencilBtn;
Image image;
Pane rootPane;
HBox pictureRegion;
Scene scene;
Rectangle croppedArea;
Canvas canvas;
GraphicsContext gc;
WritableImage writableImage;
Group group = new Group();
Line line;
LineTo lineTo;
String shape;
Boolean canvasAdded;
#Override
public void start(Stage primaryStage) {
try {
int sleepTime = 120;
Thread.sleep(sleepTime);
pencilBtn = createButton("save.png");
pictureRegion = new HBox();
rootPane = new Pane();
scene = new Scene(rootPane);
robot = new Robot();
java.awt.Rectangle capture = new java.awt.Rectangle(Toolkit.getDefaultToolkit().getScreenSize());
bufferedImage = robot.createScreenCapture(capture);
image = ConvertBufferedToJavaFXImage.convertToFxImage(bufferedImage);
pencilBtn.setOnAction(e -> geometrySelection("pencil"));
croppedArea = new Rectangle();
if(canvas != null) {
canvas.setOnMousePressed(e -> onMousePressed(e));
canvas.setOnMousePressed(e -> onMouseDragged(e));
}
imageView = new ImageView(image);
scene.setOnMouseEntered(e -> onMouseEntered(e, "scene"));
scene.setOnMousePressed(e -> onMousePressed(e));
scene.setOnMouseReleased(e -> onMouseReleased(e));
scene.setOnMouseDragged(e -> onMouseDragged(e));
pictureRegion.getChildren().add(imageView);
rootPane.getChildren().add(pictureRegion);
rootPane.getChildren().add(group);
scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
primaryStage.setMaximized(true);
primaryStage.setScene(scene);
primaryStage.show();
} catch (Exception e) {
e.printStackTrace();
}
}
public void onMouseEntered(MouseEvent ev, String nodeType) {
if (nodeType == "scene") {
scene.setCursor(Cursor.CROSSHAIR);
} else if (nodeType == "croppedArea") {
croppedArea.setCursor(Cursor.TEXT);
//croppedArea.setOnMousePressed(e -> onMousePressed(e));
} else if (nodeType == "btn") {
pencilBtn.setCursor(Cursor.HAND);
}
}
public void onMousePressed(MouseEvent event) {
if ((startingPointX < event.getX() && event.getX() < currentEndingPointX)
&& (startingPointY < event.getY() && event.getY() < currentEndingPointY)) {
if(shape == "pencil") {
lineTo = new LineTo();
System.out.println("lineTo1");
gc.beginPath();
gc.lineTo(event.getX(), event.getY());
gc.stroke();
}
} else {
shape = "croppedArea";
rootPane.getChildren().remove(canvas);
group.getChildren().clear();
startingPointX = event.getX();
startingPointY = event.getY();
group.getChildren().add(croppedArea);
}
}
public void onMouseDragged(MouseEvent event) {
dragStatus = 1;
if (dragStatus == 1) {
// if((startingPointX < event.getX() && event.getX() < currentEndingPointX)
// && (startingPointY < event.getY() && event.getY() < currentEndingPointY)) {
if(shape == "pencil") {
System.out.println("lineTo1");
gc.lineTo(event.getX(), event.getY());
gc.stroke();
}
else {
currentEndingPointX = event.getX();
currentEndingPointY = event.getY();
rootPane.getChildren().remove(pencilBtn);
croppedArea.setFill(Color.TRANSPARENT);
croppedArea.setStroke(Color.BLACK);
croppedArea.setOnMouseEntered(e -> onMouseEntered(e, "croppedArea"));
adjustRectangleProperties(startingPointX, startingPointY, currentEndingPointX, currentEndingPointY,
croppedArea);
}
}
}
public void geometrySelection(String tempShape) {
if(tempShape == "pencil") {
shape = "pencil";
canvas = new Canvas();
gc = canvas.getGraphicsContext2D();
//gc.setFill(Color.LIGHTGRAY);
gc.setStroke(Color.BLACK);
gc.setLineWidth(5);
canvas.setLayoutX(startingPointX);
canvas.setLayoutY(startingPointY);
canvas.setWidth(croppedArea.getWidth());
canvas.setHeight(croppedArea.getHeight());
System.out.println("canvasAdded");
group.getChildren().add(canvas);
}
}
public void onMouseReleased(MouseEvent event) {
if(dragStatus == 1) {
if(shape == "croppedArea") {
if (croppedArea.getHeight() > 0 && croppedArea.getWidth() > 0) {
pencilBtn.setLayoutX(Math.max(startingPointX, currentEndingPointX) + 5);
pencilBtn.setLayoutY(Math.max(startingPointY, currentEndingPointY) - 120);
rootPane.getChildren().add(pencilBtn);
dragStatus = 0;
}
}
bufferedImage = robot.createScreenCapture(new java.awt.Rectangle((int) startingPointX, (int) startingPointY,
(int) croppedArea.getWidth(), (int) croppedArea.getHeight()));
}
}
void adjustRectangleProperties(Double startingPointX, Double startingPointY, Double currentEndingPointX,
Double currentEndingPointY, Rectangle givenRectangle) {
givenRectangle.setX(startingPointX);
givenRectangle.setY(startingPointY);
givenRectangle.setWidth(currentEndingPointX - startingPointX);
givenRectangle.setHeight(currentEndingPointY - startingPointY);
if (givenRectangle.getWidth() < 0) {
givenRectangle.setWidth(-givenRectangle.getWidth());
givenRectangle.setX(givenRectangle.getX() - givenRectangle.getWidth());
}
if (givenRectangle.getHeight() < 0) {
givenRectangle.setHeight(-givenRectangle.getHeight());
givenRectangle.setY(givenRectangle.getY() - givenRectangle.getHeight());
}
}
public Button createButton(String imageName) throws FileNotFoundException {
FileInputStream iconFile = new FileInputStream(imageName);
Image iconImage = new Image(iconFile);
Button button = new Button();
button.setGraphic(new ImageView(iconImage));
button.setMaxSize(20, 20);
button.setPadding(Insets.EMPTY);
return button;
}
public static void main(String[] args) {
launch(args);
}
}
`
I'm trying to build a FadeIn/Out animation on a window (stage). If the mouse moves into the stage it should fade in and if the mouse leaves it should fade out.
I created a Timeline that modifies the stage.opacityProperty() to achieve this. I ran into problems when I set the stage style transparent like this stage.initStyle(StageStyle.TRANSPARENT);. If I do so, the fading will not be visible. The Timeline plays the animation, but the opacity change will not be rendered by JavaFX. When setting the stageStyle to default, everything works fine and the window plus its decoration will fade in and out.
I want this effect to work in TRANSPARENT stage style so i tried the following:
I put a label onto the scene and change its textproperty in another Timeline. I now update the label text every 400msecs. If i do so, the opacity change will be rendered on every label-change.
This brings me to the conclusion, that modifying the opacity in TRANSPARENT stage style, will not result in a repaint of the stage.
Modifying the label text will result in repaint. Does this mean, that i cannot fade a stage in TRANSPARENT stage style, if the content does not change?
Is this a bug or am I doing something wrong?
I've made an SSCCE that reproduces the problem. If you remove the line stage.initStyle(StageStyle.TRANSPARENT); the fadeIn/out animation will run smoothly.
package de.schuette.jfx.stage_opacity_bug;
import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.input.KeyCode;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import javafx.util.Duration;
public class FadeApp extends Application {
public static void main(String[] args) {
Application.launch(args);
}
private Label label;
#Override
public void start(Stage stage) {
if (stage == null)
throw new IllegalArgumentException("No stage was set.");
this.label = new Label("HALLO WELT");
Scene scene = new Scene(label, 300, 300);
scene.setOnKeyPressed(e -> {
if (e.getCode() == KeyCode.ESCAPE) {
stage.close();
}
});
stage.setScene(scene);
stage.setOpacity(1);
stage.initStyle(StageStyle.TRANSPARENT);
stage.setTitle("Opacity change does result in repaint when stage style is transparent.");
stage.setAlwaysOnTop(true);
stage.show();
Platform.runLater(() -> {
Timeline t = new Timeline(new KeyFrame(Duration.millis(0),
new KeyValue(stage.opacityProperty(), 1)), new KeyFrame(
Duration.millis(500), new KeyValue(stage.opacityProperty(),
0)));
t.setAutoReverse(true);
t.setCycleCount(Timeline.INDEFINITE);
t.playFromStart();
});
Platform.runLater(() -> {
Timeline t = new Timeline(new KeyFrame(Duration.millis(400), e -> {
label.textProperty().set(String.valueOf(Math.random()));
}));
t.setCycleCount(Timeline.INDEFINITE);
t.playFromStart();
});
}
}
I'm currtently working with
Java(TM) SE Runtime Environment (build 1.8.0_20-b26)
Windows 7 x64 Professional
With the help of the JavaFX developer team I was able to find a workaround for this problem. Using a custom linear interpolator that changes the scene's fill property and immediately change it back to its original value will cause a repaint on the stage. This is done by the "bugFixInterpolator" in the code below:
package de.schuette.jfx.stage_opacity_bug;
import javafx.animation.Interpolator;
import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.input.KeyCode;
import javafx.scene.paint.Color;
import javafx.scene.paint.Paint;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import javafx.util.Duration;
public class FadeApp extends Application {
public static void main(String[] args) {
Application.launch(args);
}
private Label label;
/*
* (non-Javadoc)
*
* #see javafx.application.Application#start(javafx.stage.Stage)
*/
#Override
public void start(Stage stage) {
if (stage == null)
throw new IllegalArgumentException("No stage was set.");
this.label = new Label("HELLO WORLD");
Scene scene = new Scene(label, 300, 300);
scene.setOnKeyPressed(e -> {
if (e.getCode() == KeyCode.ESCAPE) {
stage.close();
}
});
stage.setScene(scene);
stage.setOpacity(1);
stage.initStyle(StageStyle.TRANSPARENT);
stage.setTitle("Opacity change does result in repaint when stage style is transparent.");
stage.setAlwaysOnTop(true);
stage.show();
Interpolator bugFixInterpolator = new Interpolator() {
#Override
protected double curve(double t) {
Paint fill = scene.getFill();
scene.setFill(Color.RED);
scene.setFill(fill);
return t;
}
#Override
public String toString() {
return "Interpolator.LINEAR";
}
};
Timeline t = new Timeline(new KeyFrame(Duration.millis(0),
new KeyValue(stage.opacityProperty(), 1, bugFixInterpolator)),
new KeyFrame(Duration.millis(500), new KeyValue(stage
.opacityProperty(), 0, bugFixInterpolator)));
t.setAutoReverse(true);
t.setCycleCount(Timeline.INDEFINITE);
t.playFromStart();
t = new Timeline(new KeyFrame(Duration.millis(400), e -> {
label.textProperty().set(String.valueOf(Math.random()));
}));
t.setCycleCount(Timeline.INDEFINITE);
t.playFromStart();
}
}
So i have this code in which i'm trying to do a scene for my game. I'm really a beginner in a Java and especially JAVAFX world and doing this as a school project (Once again..) and trying to figure out a way to refresh my label.
I've found one URL from stackoverflow, which was a similar issue but didn't work for my problem (or was i too stupid to make it work..) anyways, link is here
This is the part where the problem occurs - i have a text box, from which you have to enter player names. Every time a user inputs player name the label shows how many names have been entered, according to the nimedlist.size() which holds the names inside.
Label mängijate_arv = new Label("Mängijaid on sisestatud: "+nimedlist.size());
// if we press enter, program will read the name
nimiTekst.setOnKeyPressed(new EventHandler<KeyEvent>() {
public void handle(final KeyEvent keyEvent) {
if (keyEvent.getCode() == KeyCode.ENTER) {
if (nimiTekst.getText() != null) {
nimedlist.add(nimiTekst.getText());
nimiTekst.setText(null);
}
}
}
});
startBox.getChildren().addAll(sisestus_mängijad, nimiTekst, mängijate_arv,
startButton2);
This is the whole code:
package application;
import java.util.ArrayList;
import javafx.application.Application;
import javafx.beans.property.StringProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.ListView;
import javafx.scene.control.RadioButton;
import javafx.scene.control.TextField;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.FlowPane;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import javafx.stage.Stage;
import javafx.stage.WindowEvent;
public class Baila2 extends Application {
public static void main(String[] args) {
launch(args);
}
public void start(final Stage peaLava) {
final Group root = new Group();
final BorderPane piir = new BorderPane();
piir.setPrefSize(960, 540);
final Text tekst = new Text();
tekst.setText("JOOMISMÄNG");
tekst.setFont(Font.font("Verdana", 40));
VBox nupudAlam = new VBox();
Button startButton = new Button("Start");
nupudAlam.setSpacing(20);
Button reeglidButton = new Button("Reeglid");
nupudAlam.setAlignment(Pos.CENTER);
startButton.setId("btn3");
startButton.setMaxWidth(160);
reeglidButton.setMaxWidth(160);
reeglidButton.setId("btn3");
nupudAlam.getChildren().addAll(startButton, reeglidButton);
piir.setTop(tekst);
piir.setAlignment(tekst, Pos.CENTER);
piir.setCenter(nupudAlam);
root.getChildren().add(piir);
// START NUPP TÖÖ
startButton.setOnAction(new EventHandler<ActionEvent>() {
public void handle(final ActionEvent event) {
final ArrayList nimedlist = new ArrayList();
piir.setVisible(false);
final BorderPane startPiir = new BorderPane();
final VBox startBox = new VBox();
Button startButton2 = new Button("ALUSTA!");
startButton2.setId("btn2");
startButton2.setMaxWidth(160);
startPiir.setPrefSize(960, 540);
final Text startTekst = new Text();
startTekst.setText("JOOMISMÄNG");
startTekst.setFont(Font.font("Verdana", 40));
startPiir.setTop(startTekst);
startPiir.setAlignment(startTekst, Pos.CENTER);
final TextField nimiTekst = new TextField();
nimiTekst.setText(null);
nimiTekst.setMaxWidth(250);
Label sisestus_mängijad = new Label(
"Sisesta 3-9 mängija nimed:");
sisestus_mängijad.setFont(Font.font("Verdana", 30));
sisestus_mängijad.setTextFill(Color.ORANGE);
Label mängijate_arv = new Label("Mängijaid on sisestatud: "+nimedlist.size());
// kui vajutatakse ENTER,siis loeme nime
nimiTekst.setOnKeyPressed(new EventHandler<KeyEvent>() {
public void handle(final KeyEvent keyEvent) {
if (keyEvent.getCode() == KeyCode.ENTER) {
if (nimiTekst.getText() != null) {
nimedlist.add(nimiTekst.getText());
nimiTekst.setText(null);
}
}
}
});
startBox.getChildren().addAll(sisestus_mängijad, nimiTekst, mängijate_arv,
startButton2);
startBox.setSpacing(20);
startBox.setAlignment(Pos.CENTER);
startPiir.setCenter(startBox);
root.getChildren().add(startPiir);
}
});
// aknasündmuse lisamine
peaLava.setOnHiding(new EventHandler<WindowEvent>() {
public void handle(WindowEvent event) {
// luuakse teine lava
final Stage kusimus = new Stage();
// küsimuse ja kahe nupu loomine
Label label = new Label("Kas tõesti tahad kinni panna?");
Button okButton = new Button("Jah");
Button cancelButton = new Button("Ei");
// sündmuse lisamine nupule Jah
okButton.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent event) {
kusimus.hide();
}
});
// sündmuse lisamine nupule Ei
cancelButton.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent event) {
peaLava.show();
kusimus.hide();
}
});
// nuppude grupeerimine
FlowPane pane = new FlowPane(10, 10);
pane.setAlignment(Pos.CENTER);
pane.getChildren().addAll(okButton, cancelButton);
// küsimuse ja nuppude gruppi paigutamine
VBox vBox = new VBox(10);
vBox.setAlignment(Pos.CENTER);
vBox.getChildren().addAll(label, pane);
// stseeni loomine ja näitamine
Scene stseen2 = new Scene(vBox);
kusimus.setScene(stseen2);
kusimus.show();
}
}); // siin lõpeb aknasündmuse kirjeldus
// stseeni loomine ja näitamine
Scene stseen1 = new Scene(root, 960, 540, Color.GREEN);
peaLava.setTitle("BAILA 2.0");
// peaLava.setResizable(false);
stseen1.getStylesheets().add(
getClass().getClassLoader().getResource("test.css")
.toExternalForm());
peaLava.setScene(stseen1);
peaLava.show();
}
}
Sorry about Estonian language, it's compulsory in our school to write in our native language..
You can just do
nimiTekst.setOnKeyPressed(new EventHandler<KeyEvent>() {
public void handle(final KeyEvent keyEvent) {
if (keyEvent.getCode() == KeyCode.ENTER) {
if (nimiTekst.getText() != null) {
nimedlist.add(nimiTekst.getText());
nimiTekst.setText(null);
mängijate_arv.setText("Mängijaid on sisestatud: "+nimedlist.size());
}
}
}
});
If you are not using Java 8 (you appear not to be, since you are implementing all the handlers the old, long way...), you will have to declare mängijate_arv as final:
final Label mängijate_arv = new Label("Mängijaid on sisestatud: "+nimedlist.size());
If you want to be extra cool with this, you can use bindings instead. You will have to make nimidlist an observable list:
final ObservableList<String> nimedlist = FXCollections.observableArrayList();
and then:
mängijate_arv.bind(Bindings.format("Mängijaid on sisestatud: %d", Bindings.size(nimedList)));
and don't put the mängijate_arv.setText(...) call in the handler. This solution is nicer in many ways, as if you remove items from the list (or add other items elsewhere in your code), then the label will still remain properly updated without any additional code.
One other thing: it's a bit better to use an action handler on the text field, instead of a low-level key event handler:
nimiTekst.setOnAction(new EventHandler<ActionEvent>() {
public void handle(final ActionEvent keyEvent) {
if (nimiTekst.getText() != null) {
nimedlist.add(nimiTekst.getText());
nimiTekst.setText(null);
mängijate_arv.setText("Mängijaid on sisestatud: "+nimedlist.size());
}
}
});
(Sorry if I mangled your variable names. My Estonian is a bit weak ;). Your school's policy is a good one, for what it's worth.)