I'm using following code to show some popup.
if(isIdDuplicated) {
showTooltip(stage, textField_id, "This id have already been used!");
}
public static void showTooltip(Stage owner, Control control, String tooltipText) {
Point2D p = control.localToScene(0.0, 0.0);
final Tooltip customTooltip = new Tooltip();
customTooltip.setText(tooltipText);
control.setTooltip(customTooltip);
customTooltip.show(owner, p.getX()
+ control.getScene().getX() + control.getScene().getWindow().getX(), p.getY()
+ control.getScene().getY() +
control.getScene().getWindow().getY());
}
Here is the problem I had to face: When moving the window, above help popups(actually tool tips) are not moving with the textField_id. Can anybody tell me the best way to do this like functionality without using tool tips? Is there any third party library with help popup like controls in JavaFX?
Here is an example for well known help popup:
like something like this?
#Override
public void start(Stage stage) {
stage.setTitle("My story");
BorderPane bp = new BorderPane();
bp.setStyle("-fx-background-image : url(\"http://thechronicle.com.gh/wp-content/uploads/2016/10/Juliet-Ibrahim.jpg\")");
Button b = new Button("GET TO KNOW HER");
b.setStyle("-fx-background-color : white;");
b.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent paramT) {
Popup p = new Popup();
VBox hbox = new VBox(0); //it was hbox at first
hbox.setFillWidth(true);
hbox.setPrefWidth(400);
hbox.setMinHeight(400);
hbox.setPadding(new Insets(4));
hbox.setEffect(new DropShadow());
hbox.setStyle("-fx-background-color:white; -fx-background-radius: 5;");
Label l = new Label("You see i went to school with this woman, private school, but i was little like at age 7, and she was like 14"
+ "\n see i could barely get an erection, lol, and you see we were very noisy kids, hence they seniors always came to shut us up."
+ " see i was a very very bad 7 year old, and you know how these teen chicks they love bad kids, lol. but i was too young.");
l.setWrapText(true);
l.setPrefWidth(400);
l.setStyle("-fx-background-color:white;");
HBox.setHgrow(l, Priority.SOMETIMES);
Label l1 = new Label("Look at her y'all, she married though, but you know crazy me, i had all these and i i fell in love with ruby and some chick name java"
+ ", i dont know what i was thinking,"
+ " i dont know who cursed me, lol, shit, here name is Juiliet Ibrahim. lol, thats my sister,"
+ " you see its not very hard to replicate, i have lights out, runing on a 30 mins laptop, this demo, i will pimp it tomorrow,"
+ " aka - show you more pics of my sister lol.");
l1.setWrapText(true);
l1.setPrefWidth(400);
l1.setStyle("-fx-background-color:white; -fx-text-fill: black;");
HBox.setHgrow(l1, Priority.SOMETIMES);
Label l2 = new Label("THIS IS A POP UP MENU");
l2.setWrapText(true);
l2.setPrefWidth(400);
l2.setStyle("-fx-background-color:blueviolet; -fx-text-fill: white;");
l2.setFont(Font.font(Font.getFontNames().get(18), FontWeight.EXTRA_BOLD, 22));
HBox.setHgrow(l1, Priority.SOMETIMES);
hbox.getChildren().addAll(l,
new HBox(new ImageView(new Image("https://s-media-cache-ak0.pinimg.com/originals/82/57/c1/8257c1c3e05d3e5c0d8a945e9d1b8a11.jpg",133,0,true,true,true)),
new ImageView(new Image("https://www.bellanaija.com/wp-content/uploads/2016/03/Juliet-Ibrahim-2-600x867.jpg",133,0,true,true,true)),
new ImageView(new Image("http://www.gistus.com/gs-c/uploads/2015/10/juliet8.jpg",133,0,true,true,true))),
l1,l2);
p.getContent().add(hbox);
p.setAnchorX(b.getLayoutX() + b.getTranslateX() + stage.getX()+ b.prefWidth(-1) + 5);//just for demo
p.setAnchorY(b.getLayoutY() + b.getTranslateY() + stage.getY()+ b.prefHeight(-1));//just for demo
//for demostration sake
Bindings.createDoubleBinding(new Callable<Double>() {
#Override
public Double call() throws Exception {
return 0.0;
}
}, stage.xProperty(),stage.yProperty());
new DoubleBinding() {
{
super.bind(stage.xProperty());
super.bind(stage.yProperty());
}
#Override
protected double computeValue() {
return stage.xProperty().add(stage.yProperty()).get();//dont try this at work :)
}
}.addListener(new ChangeListener<Number>() {
#Override
public void changed(ObservableValue<? extends Number> paramObservableValue, Number paramT1,
Number paramT2) {
p.setAnchorX(b.getLayoutX() + b.getTranslateX() + stage.getX()+ b.prefWidth(-1) + 5);//just for demo
p.setAnchorY(b.getLayoutY() + b.getTranslateY() + stage.getY()+ b.prefHeight(-1));//just for demo
}
});
p.setAutoFix(true);
p.show(stage);
}
});
bp.setBottom(b);
stage.setScene(new Scene(bp,600,500));
stage.show();
}
Related
So, for my class project I am making a game. I want to add a volume slider to change the music volume. I am very stuck here. Please help me.
I was following tutorial, and I was able to display it on the scree. But, the volume doesn't change, even though I slide the bar. Can somebody give me advice? Thank you.
private Scene createOptionScene() {
String path = "E:\\All Computer Science Materials\\Java 240 Project\\PrinceFX\\Music\\"
+ songs.getSong(1) + ".mp3";
Media media = new Media(new File(path).toURI().toString());
currentPlay = new AudioClip(media.getSource());
currentPlay.setCycleCount(MediaPlayer.INDEFINITE);
currentPlay.play();
// Volume Control
volumeSlider.setValue(currentPlay.getVolume() * 100);
volumeSlider.valueProperty().addListener(new InvalidationListener() {
#Override
public void invalidated(Observable observable) {
currentPlay.setVolume(volumeSlider.getValue() / 100);
}
});
HBox temp = new HBox();
temp.getChildren().addAll(volumeSlider);
temp.setTranslateX(850);
temp.setTranslateY(410);
volumeSlider.setMinWidth(300);
Image image = new Image(new File("E:\\All Computer Science Materials\\" +
"Java 240 Project\\PrinceFX\\image\\" + picture.getImage(2) + ".png").toURI().toString());
//Setting the image view
ImageView imageView = new ImageView(image);
//Setting the position of the image
imageView.setX(0);
imageView.setY(0);
//setting the fit height and width of the image view
imageView.setFitHeight(primaryScreenBounds.getHeight());
imageView.setFitWidth(primaryScreenBounds.getWidth());
//Setting the preserve ratio of the image view
imageView.setPreserveRatio(true);
Label labelOption = new Label();
Button goBack = new Button("Go Back to Main");
goBack.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
currentPlay.stop();
sceneStart = createStartScene();
stageOne.setScene(sceneStart);
}
});
// Button to the main page.
HBox layoutOp = new HBox(15);
layoutOp.getChildren().addAll(labelOption, goBack);
// Button coordinate.
layoutOp.setTranslateX(1400);
layoutOp.setTranslateY(750);
Group gOption = new Group(imageView, layoutOp, temp);
return new Scene(gOption, 200, 200);
}
currently stuck with a problem in JavaFX, trying to create a cookie clicker game, so i've created a button "Clicker" which automatically, once every 5 seconds, clicks the cookie. Im trying to make my timeline 0.1 seconds faster everytime i buy another clicker, currently, i've been trying it like this:
private double clickerSpeed = 5.1;
Timeline clickerPoints = new Timeline();
KeyFrame kfClicker = new KeyFrame(Duration.seconds(clickerSpeed),
event -> {
cookieClicker.cookies += cookieClicker.cursor.getProdRate();
cookieButton.setText("Cookies = " + cookieClicker.cookies);
});
clickerPoints.getKeyFrames().add(kfClicker);
clickerPoints.setCycleCount(Timeline.INDEFINITE);
buyClicker.setOnAction(event -> {
if (clickerSpeed >= 1 && cookieClicker.cookies >=
cookieClicker.clicker.getCosts()) {
clickerSpeed -= 0.1; ## In theory, this should make the keyframe faster?
}
cookieClicker.buyClicker();
clickerLabel.setText(cookieClicker.clicker.getName() + "s: " +
cookieClicker.clicker.getLevel());
buyClicker.setText("Buy clicker for: " +
cookieClicker.clicker.getCosts());
cookieButton.setText("Cookies = " + cookieClicker.cookies);
clickerPoints.play();
Modifying a primitive double does not have any effect on values read before; the duration is not automatically adjusted.
To speed up the Timeline you should modify the rate property instead.
The following example shows how to update the duration an animation takes to animate fading a Rectangle from 10 seconds to 1 second in 1 second steps:
#Override
public void start(Stage primaryStage) throws Exception {
Rectangle rect = new Rectangle(100, 100);
Button btn = new Button("Speed Up");
HBox root = new HBox(rect, btn);
Timeline timeline = new Timeline(
new KeyFrame(Duration.ZERO, new KeyValue(rect.opacityProperty(), 1d)),
new KeyFrame(Duration.seconds(10), new KeyValue(rect.opacityProperty(), 0d))
);
timeline.setCycleCount(Animation.INDEFINITE);
timeline.play();
btn.setOnAction(new EventHandler<ActionEvent>() {
private double duration = timeline.getCycleDuration().toSeconds();
#Override
public void handle(ActionEvent event) {
if (duration > 1) {
duration--;
timeline.setRate(timeline.getCycleDuration().toSeconds() / duration);
}
}
});
Scene scene = new Scene(root);
primaryStage.setScene(scene);
primaryStage.show();
}
I'm trying to make a program that will display a random set of 4 cards, then when I click the button again it will clear the old set and display a new random set.
Right now my program will display 4 random images of cards when I click the button; however, when I try to click it again nothing happens. I'm assuming it has something to do with the EventHandler no longer being registered to the button after I clear the root children. However, I don't know how to go about fixing this. Any help is greatly appreciated! I haven't been able to find an answer to this yet, and have only been learning JavaFX for about a week. Thank you.
The code I have so far:
public class CardShuffle extends Application {
#Override
public void start(Stage primaryStage) throws Exception {
StackPane root = new StackPane();
Scanner input = new Scanner(System.in);
File cardsFolder = new File("C:\\Users\\timsp\\Pictures\\JPEG");
ArrayList<File> cardsFilePaths = new ArrayList<File> (Arrays.asList(cardsFolder.listFiles()));
Button deal = new Button("DEAL");
Pane hb = new HBox(10);
hb.setPadding(new Insets(5, 5, 5, 5));
root.getChildren().add(deal);
deal.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
root.getChildren().clear();
ArrayList<ImageView> cards = getRandomCards(cardsFilePaths);
for (int i = 0; i < 4; i++) {
cards.get(i).setFitWidth(150);
cards.get(i).setFitHeight(100);
hb.getChildren().add(cards.get(i));
}
root.getChildren().addAll(deal, hb);
}
});
Scene scene = new Scene(root, 800, 600);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
public ArrayList<ImageView> getRandomCards(ArrayList<File> cardsFilePaths) {
ArrayList<ImageView> cards = new ArrayList<ImageView>();
try {
for (int i = 0; i < 4; i++) {
Image card = new Image((new FileInputStream(cardsFilePaths.get((int) (Math.random() * 52)).getPath())));
ImageView temp = new ImageView();
temp.setImage(card);
cards.add(temp);
}
} catch (FileNotFoundException e) {
e.getMessage();
}
return cards;
}
}
Many problems here :
the first one, and the most important (because it hides your further error) is the root layout : you use a StackPane, the first thing you should do is to replace it by a VBox for example and rerun your program, it will be easier to see what really happens. (you will not have 4 cards, but 8, 12, 16 and so on).
the first one generates the second one. By doing this root.getChildren().addAll(deal, hb); you put the HBox layout above the button, and the click is first consumed by the HBox. Here is an example to see it more easily :
// Add the HBox as soon as the initialization
root.getChildren().add(deal);
hb.setOnMouseClicked(e -> System.out.println("HBox clicked"));
deal.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
root.getChildren().clear();
ArrayList<ImageView> cards = getRandomCards(cardsFilePaths);
for(int i = 0; i < 4; i++) {
cards.get(i).setFitWidth(150);
cards.get(i).setFitHeight(100);
hb.getChildren().add(cards.get(i));
}
hb.setStyle("-fx-background-color:CORNFLOWERBLUE;-fx-opacity:0.8;");
root.getChildren().addAll(deal, hb);
}
});
And the last one, you don't really want to remove all root's children, what you want is to replace your cards by another 4 ones. Thus it is not necessary to remove the button, only the HBox can be manipulated as shown by the following example :
// Add the HBox as soon as the initialization
root.getChildren().addAll(hb, deal);
deal.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
// root.getChildren().clear();
// Replace the previous line by the following :
hb.getChildren().clear();
ArrayList<ImageView> cards = getRandomCards(cardsFilePaths);
for(int i = 0; i < 4; i++) {
cards.get(i).setFitWidth(150);
cards.get(i).setFitHeight(100);
hb.getChildren().add(cards.get(i));
}
// The following is useless now.
// root.getChildren().addAll(hb, deal);
}
});
Is it possible to add .hoverProperty().addListener to all children(in my case buttons) of HBox? I know that I can assign separate listeners for each button. But I was interested if it is possible to assign one listener to all children at once. Buttons of HBox have 15 px spacing between them.
Just add the listener to the HBox:
public class Main extends Application {
#Override
public void start(Stage primaryStage) {
Group root = new Group();
HBox hBox = new HBox();
hBox.setSpacing(30);
for (int i = 0; i < 10; i++) {
hBox.getChildren().add(new Button("Button " + i));
}
hBox.hoverProperty().addListener(new ChangeListener<Boolean>() {
#Override
public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
System.out.println("Hover: " + oldValue + " -> " + newValue);
}
});
hBox.addEventFilter(MouseEvent.MOUSE_ENTERED, e -> System.out.println( e));
hBox.addEventFilter(MouseEvent.MOUSE_EXITED, e -> System.out.println( e));
hBox.addEventFilter(MouseEvent.MOUSE_MOVED, e -> {
if( e.getTarget() instanceof Button) {
System.out.println( e);
}
});
hBox.setMaxHeight(100);
root.getChildren().add( hBox);
Scene scene = new Scene( root, 800, 500);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
According to the hoverProperty documentation you could as well use a mouse listener for now:
Note that current implementation of hover relies on mouse enter and
exit events to determine whether this Node is in the hover state; this
means that this feature is currently supported only on systems that
have a mouse. Future implementations may provide alternative means of
supporting hover.
A few days ago I started studying JavaFX, and came across the desire to perform 2 experiments. Firstly, I would like to know if it is possible to put an animated background behind an user interface. I've succeeded in creating an animated background, and now I'm having great difficulties to position some controls in the middle of my interface.
I'd like to introduce you 2 pictures of my program. The first demonstrates the undesirable result that I'm getting:
I believe this is my nodes tree:
This is the code of my application:
public class AnimatedBackground extends Application
{
// #########################################################################################################
// MAIN
// #########################################################################################################
public static void main(String[] args)
{
Application.launch(args);
}
// #########################################################################################################
// INSTÂNCIAS
// #########################################################################################################
private Group root;
private Group grp_hexagons;
private Rectangle rect_background;
private Scene cenario;
// UI
private VBox lay_box_controls;
private Label lab_test;
private TextArea texA_test;
private Button bot_test;
// #########################################################################################################
// INÍCIO FX
// #########################################################################################################
#Override public void start(Stage stage) throws Exception
{
this.confFX();
cenario = new Scene(this.root , 640 , 480);
this.rect_background.widthProperty().bind(this.cenario.widthProperty());
this.rect_background.heightProperty().bind(this.cenario.heightProperty());
stage.setScene(cenario);
stage.setTitle("Meu programa JavaFX - R.D.S.");
stage.show();
}
protected void confFX()
{
this.root = new Group();
this.grp_hexagons = new Group();
// Initiate the circles and all animation stuff.
for(int cont = 0 ; cont < 15 ; cont++)
{
Circle circle = new Circle();
circle.setFill(Color.WHITE);
circle.setEffect(new GaussianBlur(Math.random() * 8 + 2));
circle.setOpacity(Math.random());
circle.setRadius(20);
this.grp_hexagons.getChildren().add(circle);
double randScale = (Math.random() * 4) + 1;
KeyValue kValueX = new KeyValue(circle.scaleXProperty() , randScale);
KeyValue kValueY = new KeyValue(circle.scaleYProperty() , randScale);
KeyFrame kFrame = new KeyFrame(Duration.millis(5000 + (Math.random() * 5000)) , kValueX , kValueY);
Timeline linhaT = new Timeline();
linhaT.getKeyFrames().add(kFrame);
linhaT.setAutoReverse(true);
linhaT.setCycleCount(Animation.INDEFINITE);
linhaT.play();
}
this.rect_background = new Rectangle();
this.root.getChildren().add(this.rect_background);
this.root.getChildren().add(this.grp_hexagons);
// UI
this.lay_box_controls = new VBox();
this.lay_box_controls.setSpacing(20);
this.lay_box_controls.setAlignment(Pos.CENTER);
this.bot_test = new Button("CHANGE POSITIONS");
this.bot_test.setAlignment(Pos.CENTER);
this.bot_test.setOnAction(new EventHandler<ActionEvent>()
{
#Override public void handle(ActionEvent e)
{
for(Node hexagono : grp_hexagons.getChildren())
{
hexagono.setTranslateX(Math.random() * cenario.getWidth());
hexagono.setTranslateY(Math.random() * cenario.getHeight());
}
}
});
this.texA_test = new TextArea();
this.texA_test.setText("This is just a test.");
this.lab_test = new Label("This is just a label.");
this.lab_test.setTextFill(Color.WHITE);
this.lab_test.setFont(new Font(32));
this.lay_box_controls.getChildren().add(this.lab_test);
this.lay_box_controls.getChildren().add(this.texA_test);
this.lay_box_controls.getChildren().add(this.bot_test);
this.root.getChildren().add(this.lay_box_controls);
}
}
I've tried to make the use of a StackPane as the root of my scene graph, but also found an undesired result. Despite the controls have stayed in the center of the window, the circles begin to move in as they grow and shrink, making it appear that everything is weird.
The second thing I would like to know is if it is possible to customize the controls so they perform some animation when some event happens. Although we can change the appearance of controls using CSS, it's harder to create something complex. For example, when a control changes its appearance due to a change of state, the transition state change is not made in an animated way, but in an abrupt and static way. Is there a way to animate, for example, a button between its states? This would be done using the JavaFX API? Or would that be using CSS? Or would not be possible in any way?
Thank you for your attention.
after much struggle, I and some users of the Oracle community could resolve this issue. I see no need to repeat here all the resolution made by us, so I'll post the link so you can access the solution of the problem. I hope this benefits us all. Thanks for your attention anyway.
https://community.oracle.com/thread/2620500