Javafx GUI programming - user-interface

So im trying to make 3 buttons on the top panel and 3 radio buttons on the bottom panel, but when i run it, it comes out all weird, would love it if someone can help me. Im still pretty new to GUI so my code might be completely wrong.
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.RadioButton;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.paint.Color;
public class ColorFactory extends Application {
#Override
public void start(Stage stage)
{
BorderPane pane = new BorderPane();
// sets the width and height
stage.setHeight(300);
stage.setWidth(500);
//calls the mainpanel constructor
pane.setCenter(new MainPanel());
//make the mainpanel visible using the setVisible(true)
//call the stage.setScene
stage.setScene(new Scene(pane));
// set title to Color Factory
stage.setTitle("Color Factory");
//call stage.show
stage.show();
}
private class MainPanel extends BorderPane
{
public MainPanel()
{
HBox Tpanel = new HBox(25);
Tpanel = new HBox(25);
Tpanel.setPrefWidth(500);
Tpanel.setPrefHeight(50);
Tpanel.setAlignment(Pos.TOP_CENTER);
Button red = new Button("Red");
red.setStyle("-fx-background-color: red");
Button yellow = new Button("Yellow");
yellow.setStyle("-fx-background-color: yellow;");
Button orange = new Button("Orange");
orange.setStyle("-fx-background-color: orange;");
Tpanel.setStyle("-fx-background-color: white;");
Tpanel.getChildren().addAll(red,yellow,orange);
HBox Bpanel = new HBox(15);
Bpanel.setPrefWidth(500);
Bpanel.setPrefHeight(75);
RadioButton green = new RadioButton("Green");
RadioButton blue = new RadioButton("Blue");
RadioButton cyan = new RadioButton("Cyan");
green.setStyle("-fx-background-color: green;");
blue.setStyle("-fx-background-color: blue;");
cyan.setStyle("-fx-background-color: cyan;");
Bpanel.setAlignment(Pos.BOTTOM_CENTER);
Bpanel.getChildren().addAll(green,blue,cyan);
Label label = new Label("Top buttons change the panel color and bottom radio buttons change the text color");
label.setAlignment(Pos.CENTER_LEFT);
label.setTextFill(Color.BLUE);
getChildren().addAll(Tpanel,Bpanel,label);
HBox.setMargin(Tpanel, new Insets(5,10,5,10));
HBox.setMargin(Bpanel, new Insets(5,10,5,10));
HBox.setMargin(label, new Insets(150,10,5,10));
}
}
public static void main(String[] args) {
launch(args);
}
}

Your MainPanel is a BorderPane: simply adding nodes to it will put them all in the top left by default (so they are all on top of each other). When using a BorderPane, you need to call setCenter(...), setTop(...), setLeft(...) etc to position the nodes.
E.g.:
// getChildren().addAll(Tpanel,Bpanel,label);
setTop(Tpanel);
setBottom(Bpanel);
setCenter(label);

Related

Change a circle to a square to fill a square in JavaFX

I found an amazing animation in which there is transition from circle/ellipse to square and just before the end of the animation, the square protrudes out a little and then adjusts itself it back to the correct size.
Source: https://clementmihailescu.github.io/Pathfinding-Visualizer/#
I tried to recreate it but I am not able to get the transition effect from a drop of ink to square.
package sample;
import javafx.animation.*;
import javafx.application.Application;
import javafx.scene.layout.Pane;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.effect.Lighting;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.text.Text;
import javafx.util.Duration;
public class Main extends Application {
#Override
public void start(Stage primaryStage) throws Exception {
Pane root = new Pane();
Rectangle originalRectangle = new Rectangle(100,100);
originalRectangle.setFill(Color.WHITE);
originalRectangle.setStroke(Color.BLUE);
Rectangle substituteRectangle = new Rectangle(25,25,50,50);
substituteRectangle.setOpacity(0.0);
substituteRectangle.setFill(Color.TURQUOISE);
substituteRectangle.setStroke(Color.TURQUOISE);
Rectangle yellowRectangle = new Rectangle(100,100);
yellowRectangle.setFill(Color.YELLOW);
root.getChildren().addAll(originalRectangle,substituteRectangle,yellowRectangle);
FadeTransition fadeOutTransition = new FadeTransition(Duration.millis(3000),yellowRectangle); //Make the duration as 1ms to get the instant
fadeOutTransition.setFromValue(1.0);
fadeOutTransition.setToValue(0.0);
FadeTransition fadeInTransition = new FadeTransition(Duration.millis(1),substituteRectangle);
fadeInTransition.setFromValue(0.0);
fadeInTransition.setToValue(0.8);
//To make the square protrute out a bit
ScaleTransition scaleTransition = new ScaleTransition(Duration.seconds(4),substituteRectangle);
scaleTransition.setToX(2.1);
scaleTransition.setToY(2.1);
ParallelTransition parallelTransition = new ParallelTransition(scaleTransition,fadeInTransition);
fadeOutTransition.play();
fadeOutTransition.setOnFinished(e -> {
parallelTransition.setOnFinished(event -> {
root.getChildren().removeAll(substituteRectangle,yellowRectangle);
originalRectangle.setOpacity(1.0);
originalRectangle.setFill(Color.RED);
});
parallelTransition.play();
});
Scene scene = new Scene(root,800,600);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
Application.launch(args);
}
}
The probably simplest way of achieving this kind of animation would be to simply animate the radius of the circle and constrain it's size using a Rectangle as clip. Also often Timeline provides a animation that is well suited to replace multiple transitions. In this case the fact that it allows for animations between colors as well as animations for a DoubleProperty makes this a good choice for simplifying the animations:
#Override
public void start(Stage primaryStage) throws Exception {
Pane root = new Pane();
Rectangle bounds = new Rectangle(50, 50, 100, 100);
Circle circle = new Circle(bounds.getX() + 0.5 * bounds.getWidth(), bounds.getY() + 0.5 * bounds.getHeight(),
0);
circle.setClip(bounds);
root.getChildren().add(circle);
Timeline animation = new Timeline(
new KeyFrame(Duration.ZERO, new KeyValue(circle.fillProperty(), Color.BLUE),
new KeyValue(circle.radiusProperty(), 0d)),
new KeyFrame(Duration.seconds(5), new KeyValue(circle.fillProperty(), Color.RED), new KeyValue(
circle.radiusProperty(), 0.5 * Math.hypot(bounds.getWidth(), bounds.getHeight())))); // at the end of the animation the circle should reach the corners -> diameter = diagonale of rect
root.setOnMouseClicked(evt -> animation.playFromStart());
Scene scene = new Scene(root, 800, 600);
primaryStage.setScene(scene);
primaryStage.show();
}

How to change the color of the placeholder text in JavaFX TableView?

I believe it is quite simple, though I couldn't figure it out yet:
How do I change the color of the placeholder text in JavaFX TableView?
This is the placeholder text, which is shown if the table is empty:
There are (at least) two ways to solve this.
Via Css
Consult the JavaFx Css Reference and there you will see, that a TableView has an internal placeholder, that you can address using Css.
If documentation is insufficient or you need to more information about the structure of the Scenegraph, use ScenicView to explore.
Via placeholder node
Consulting the JavaFx 8 Api documentation will reveal, that there is a placeholder property, that allows you to set a custom node as placeholder.
Demo
This demo showcases both approaches:
TableViewPlaceholderFill.java:
package application;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.TableView;
import javafx.scene.layout.HBox;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;
import javafx.scene.text.FontWeight;
import javafx.stage.Stage;
public class TableViewPlaceholderFill extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) {
TableView<String> tableViaCss = new TableView<>();
tableViaCss.getStyleClass().add("my-little-pony");
TableView<String> tableWithCustomPlaceholder = new TableView<>();
final Label placeholderLabel = new Label
("Hello, Kitty!");
placeholderLabel.setFont(Font.font("monospace", FontWeight.BLACK, 16));
placeholderLabel.setTextFill(Color.HOTPINK);
tableWithCustomPlaceholder.setPlaceholder(new StackPane(placeholderLabel));
Scene scene = new Scene(new HBox(4,tableViaCss,
tableWithCustomPlaceholder));
scene.getStylesheets().add(TableViewPlaceholderFill.class
.getResource("application.css").toExternalForm());
primaryStage.setScene(scene);
primaryStage.show();
}
}
application.css:
.my-little-pony {
-fx-background-color: palevioletred;
}
.my-little-pony .placeholder .label {
-fx-text-fill: linen;
-fx-font-family: 'serif';
-fx-font-size: 1.666em;
-fx-font-weight: bold;
}

TableView columns position and TabbedPane tabs start from Right Side instead of left in JavaFX?

i've been searching for hours and could not find any way to make the tableView columns and tabs of a TabbedPane start from the right side instead of left.
As we can see in the picture java by default create them from the left side to the right, and leave empty space on the right side. Is there any way to do this vice versa ?
Thank you
see image here
Use setNodeOrientation(NodeOrientation.RIGHT_TO_LEFT);
import javafx.application.Application;
import javafx.geometry.NodeOrientation;
import javafx.scene.Scene;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.stage.Stage;
public class NodeOrientationTest extends Application {
#Override
public void start(Stage primaryStage) {
TabPane tabPane = new TabPane();
tabPane.setNodeOrientation(NodeOrientation.RIGHT_TO_LEFT);
Tab tab1 = new Tab("Tab 1");
Tab tab2 = new Tab("Tab 2");
tabPane.getTabs().addAll(tab1, tab2);
TableView<Void> table = new TableView<>();
table.setNodeOrientation(NodeOrientation.RIGHT_TO_LEFT);
table.getColumns().add(new TableColumn<Void, Void>("Column 1"));
table.getColumns().add(new TableColumn<Void, Void>("Column 2"));
tab1.setContent(table);
Scene scene = new Scene(tabPane, 800, 600);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Note that the table view will, by default, inherit this from its parent, so you can omit the call to table.setNodeOrientation(NodeOrientation.RIGHT_TO_LEFT); and achieve the same result. (Or just set it on the scene.)

When Loading Image Using BufferdImage and ImageIO it Clears my Whole Frame and Does Not Display Image

I and making a program using basic GUI involving buttons, frames, and panels, and everything was fine until I tried to load an image from my project folder. When i add the line of code
try{
titleImage = ImageIO.read(new File("mouse_title_resize.png"));
}
catch(Exception e){}
After I run the program my whole frame just becomes blank whereas before I had some JButtons on it.All the code I had before the try-catch line worked perfectly fine and I tested to see that the only thing that breaks it is this line of code. I receive no errors or anything and I have the image in my project folder and it seems that the image loaded fine, except it wont show up on the frame, and everything else on the frame disappears. I just don't understand why it clears my whole frame when i load the image.
Here is the full code:
This is the class that extends JFrame
package mouse.click.game;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.Toolkit;
import javax.swing.JFrame;
public class MouseClickGame extends JFrame {
//Constants to define the frame width and height including borders
public final int FRAME_WIDTH = 600;
public final int FRAME_HEIGHT = 600;
//Dimension from Toolkit to be able to get width and height of screen
public Dimension sizeTool = Toolkit.getDefaultToolkit().getScreenSize();
//Using sizeTool to get width of screen
public double xResolution = sizeTool.getWidth();
//Using sizeTool to get height of screen
public double yResolution = sizeTool.getHeight();
//Creating a point object that is defined as the center of the screen
public Point middleOfScreen = new Point((int) (xResolution / 2) - (FRAME_WIDTH / 2), (int) (yResolution / 2) - (FRAME_HEIGHT / 2));
public MouseClickGame() {
super("WELCOME :D");
setSize(FRAME_WIDTH, FRAME_HEIGHT);
setResizable(false);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
setLocation(middleOfScreen);
add(new MouseClickPanel());
}
public static void main(String[] args) {
//Calling constructor
MouseClickGame mainClickGame = new MouseClickGame();
}
}
And here is the class that extends JPanel (these are the only two classes in my project)
package mouse.click.game;
import java.awt.Dimension;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class MouseClickPanel extends JPanel {
JButton buttonPlay = new JButton("Play");
JButton buttonContinue = new JButton("Continue");
JButton buttonOptions = new JButton("Options");
JButton buttonExit = new JButton("Exit");
BoxLayout boxLay = new BoxLayout(this, BoxLayout.Y_AXIS);
Dimension menuButtonSize = new Dimension(300, 30);
Dimension spacingBetweenButtons = new Dimension(0, 30);
BufferedImage titleImage;
public MouseClickPanel() {
try {
titleImage = ImageIO.read(new File("C:\\Users\\Justin\\Desktop\\mouse_title.png"));
} catch (IOException e) {
}
setLayout(boxLay);
add(Box.createVerticalGlue());
add(new JLabel(new ImageIcon(titleImage)));
//Adding glue to force buttons away from top of panel
add(Box.createVerticalGlue());
add(buttonPlay);
//Vertical spacing between buttons
add(Box.createRigidArea(spacingBetweenButtons));
add(buttonContinue);
add(Box.createRigidArea(spacingBetweenButtons));
add(buttonOptions);
add(Box.createRigidArea(spacingBetweenButtons));
add(buttonExit);
//Adding glue to force buttons away from bottom of panel
add(Box.createVerticalGlue());
//Aligning all buttons to centered horizontally
buttonPlay.setAlignmentX(Box.CENTER_ALIGNMENT);
buttonContinue.setAlignmentX(Box.CENTER_ALIGNMENT);
buttonOptions.setAlignmentX(Box.CENTER_ALIGNMENT);
buttonExit.setAlignmentX(Box.CENTER_ALIGNMENT);
//Setting button sizes
buttonPlay.setMaximumSize(menuButtonSize);
buttonContinue.setMaximumSize(menuButtonSize);
buttonOptions.setMaximumSize(menuButtonSize);
buttonExit.setMaximumSize(menuButtonSize);
}
}
Literally if i get ride of the titleImage = and add(new JLabel) lines everything goes back to normal
My guess is that you've just got the path wrong -- a common mistake. In that case, you should be getting an exception like:
Exception in thread "main" javax.imageio.IIOException: Can't read input file!
at javax.imageio.ImageIO.read(ImageIO.java:1301)
at jonathanrmiproject.MyProject.main(JonathanRmiProject.java:24)
This simple example works for me:
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.naming.NamingException;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class MyProject {
public static void main(String[] args) throws NamingException, IOException {
BufferedImage img = ImageIO.read(new File("myimage.jpg"));
JLabel label = new JLabel(new ImageIcon(img));
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.getContentPane().add(label);
f.pack();
f.setLocation(200, 200);
f.setVisible(true);
}
}
I am using Netbeans IDE, and I have saved the image file to "C:\Users\David.Sharpe\MyProject\myimage.jpg".
I should add that if this is not the case, and you do have the correct path, then you need to post a more detailed question so that someone can help you. Include the code to reproduce the problem.
UPDATE: Wow literally the reason it wasn't showing up was because i called setVisble(true) too early. I can't believe it was something that simple. I guess that explains why one time everything would show up and it would be fine but then every time after nothing showed up.
So in my constructor I had
public class MouseClickGame extends JFrame {
public MouseClickGame() {
super("WELCOME :D");
setSize(FRAME_WIDTH, FRAME_HEIGHT);
setResizable(false);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocation(middleOfScreen);
setVisible(true);
add(new MouseClickPanel());
}
public static void main(String[] args) {
//Calling constructor
MouseClickGame mainClickGame = new MouseClickGame();
}
}
when all I had to do was put the setVisble() after the add(newMouseClickPanel())
Thank you DavidS for your suggestions :D

How to add an inline image to the end of a string in a TextArea in JavaFX?

I am trying to add an emoji to my chat program when my client types :)
I am trying to add this in the FXML controller. I have captured when the user types :) using the following code snippet :
if(chat.contains(":)")) {
...
}
My chat is printed into a textarea named taChat
taChat.appendText(chat + '\n');
Any help is appreciated!
A better approach would be to use TextFlow instead of using TextArea.
Advantages :
Individual Text are treated as children to the TextFlow. They can be added and accessed individually.
ImageView can be added directly to the TextFlow as a child.
A simple chat window with support for smiley :)
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TextField;
import javafx.scene.image.ImageView;
import javafx.scene.input.KeyCode;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import javafx.scene.text.Text;
import javafx.scene.text.TextFlow;
import javafx.stage.Stage;
public class ChatWindowWithSmiley extends Application {
public void start(Stage primaryStage) {
TextFlow textFlow = new TextFlow();
textFlow.setPadding(new Insets(10));
textFlow.setLineSpacing(10);
TextField textField = new TextField();
Button button = new Button("Send");
button.setPrefWidth(70);
VBox container = new VBox();
container.getChildren().addAll(textFlow, new HBox(textField, button));
VBox.setVgrow(textFlow, Priority.ALWAYS);
// Textfield re-sizes according to VBox
textField.prefWidthProperty().bind(container.widthProperty().subtract(button.prefWidthProperty()));
// On Enter press
textField.setOnKeyPressed(e -> {
if(e.getCode() == KeyCode.ENTER) {
button.fire();
}
});
button.setOnAction(e -> {
Text text;
if(textFlow.getChildren().size()==0){
text = new Text(textField.getText());
} else {
// Add new line if not the first child
text = new Text("\n" + textField.getText());
}
if(textField.getText().contains(":)")) {
ImageView imageView = new ImageView("http://files.softicons.com/download/web-icons/network-and-security-icons-by-artistsvalley/png/16x16/Regular/Friend%20Smiley.png");
// Remove :) from text
text.setText(text.getText().replace(":)"," "));
textFlow.getChildren().addAll(text, imageView);
} else {
textFlow.getChildren().add(text);
}
textField.clear();
textField.requestFocus();
});
Scene scene = new Scene(container, 300, 400);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Output
For unicode Emoji support, please visit How to support Emojis

Resources