I'm making a simple text editor for training purposes. I want to create a button which would center my text input from TextArea just like in MS Word. I have my button in FXML, but I don't know what method should I use for my TextArea object, I tried setStyle() or getChild() but neither worked.
<Button onAction="#toTheCenter" text="center"/>
Thats my button in FXML
<center>
<TextArea fx:id="textArea"/>
</center>
Thats TextArea
#FXML
private void toTheCenter(ActionEvent event){
String text = textArea.getText();
}
And thats the method from controller.
You need to set the -fx-text-alignment property on the text node of the text area.
The best way to do this dynamically is to define a custom CSS pseudoclass for the text area:
PseudoClass centered = PseudoClass.getPseudoClass("centered");
and then in your external CSS file you can do
.text-area:centered .text {
-fx-text-alignment: center ;
}
Then you can call
textArea.pseudoClassStateChanged(centered, true);
to switch centering on, and
textArea.pseudoClassStateChanged(centered, false);
to switch it off.
Here is a SSCCE (put the CSS code above in centering-text-area.css):
import javafx.application.Application;
import javafx.css.PseudoClass;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.TextArea;
import javafx.scene.control.ToggleButton;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
public class TextAreaWithCentering extends Application {
#Override
public void start(Stage primaryStage) {
TextArea textArea = new TextArea();
PseudoClass centered = PseudoClass.getPseudoClass("centered");
ToggleButton center = new ToggleButton("Center");
center.selectedProperty().addListener((obs, wasCentered, isNowCentered) ->
textArea.pseudoClassStateChanged(centered, isNowCentered));
BorderPane.setAlignment(center, Pos.CENTER);
BorderPane.setMargin(center, new Insets(5));
BorderPane root = new BorderPane(textArea, null, null, center, null);
Scene scene = new Scene(root, 600, 600);
scene.getStylesheets().add("centering-text-area.css");
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
#text-area *.text { -fx-text-alignment: center; }
Create a style.css file in your project folder and then add the following line to the java code.
scene.getStylesheets().addAll(this.getClass().getResource("style.css").toExternalForm()); primaryStage.setScene(scene);
Related
How can I create a popover like in the DatePicker class from javafx.scene.control.DatePicker as seen here:
The popover should when displayed be on top of all the other components as seen here (the popover is above the TextField):
Found a pretty simple solution to my problem, here is a code snippet in case people encounter the same problem
package main;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.CustomMenuItem;
import javafx.scene.control.Label;
import javafx.scene.control.MenuButton;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
public class Main extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) {
BorderPane rootPane = new BorderPane();
MenuButton openButton = new MenuButton("Open Context Menu");
BorderPane contentPane = new BorderPane();
CustomMenuItem item = new CustomMenuItem(contentPane);
openButton.setStyle("-fx-selection-bar: transparent;"); //this is optional. it makes the blue background that appears when something is focused transparent
contentPane.setPrefSize(300, 300);
Label text = new Label("The ContextMenu will only close when you click the\nbutton below OR click outside of the ContextMenu.\nHow neat is that?");
text.setStyle(" -fx-text-fill: -fx-text-base-color;"); //needs to bet set if you want the selection-bar to be transparent. if not set the text will become invisible
contentPane.setTop(text);
Button closeButton = new Button("Close this popover");
closeButton.setOnAction(x -> {
openButton.hide();
});
contentPane.setBottom(closeButton);
item.setHideOnClick(false); // this will stop the ContextMenu from being hidden when clicking inside of it.
openButton.getItems().add(item);
rootPane.setCenter(openButton);
Scene scene = new Scene(rootPane, 550, 250);
primaryStage.setScene(scene);
primaryStage.show();
}
}
I just placed a Pane with all of my content inside of a CustomMenuItem and added that CustomMenuItem to my MenuButton.
As stated in the title, I have fxml files, I have a UI that is set up with three labels/buttons up top and the lower half of the window has a pane. Every time a label/button is clicked, the pane must switch to that corresponding fxml file. So in other words, the pane must always be in the same position, kind of like a tabbed layout but without tabs.
I know I can achieve this with just loading a new instance of an fxml file but, I want to avoid that because when a user click on a tab he previously was on, he should be able to see his earlier input.
I have some main.java that starts the program. Some controller.java that controls the UI when it is first loaded, and some fxml file corresponding to that initial view. How can I go about implementing this transition functionality? P.S. I am very novice at JavaFX.
Here is a MCVE of how you can achieve it.
It can of course be implemented using FXML :
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TextArea;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class StageTest extends Application{
private Pane pane1, pane2, mainPane;
#Override
public void start(Stage stage) throws Exception {
stage.setTitle("Switch Panes");
Button button1 = new Button("Show Pane 1");
button1.setOnAction(e -> showPane1());
Button button2 = new Button("Show Pane 2");
button2.setOnAction(e -> showPane2());
HBox buttonsPane = new HBox(5.);
buttonsPane.getChildren().addAll(button1, button2);
pane1 = getPane("PANE ONE");
pane2 = getPane("PANE TWO");
mainPane = new StackPane(pane1);
BorderPane root = new BorderPane();
root.setTop(buttonsPane);
root.setCenter(mainPane);
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
private void showPane1() {
mainPane.getChildren().clear();
mainPane.getChildren().add(pane1);
}
private void showPane2() {
mainPane.getChildren().clear();
mainPane.getChildren().add(pane2);
}
private Pane getPane(String txt) {
VBox pane = new VBox();
pane.getChildren().addAll(new TextArea(txt+" add text here: "));
return pane;
}
public static void main(String[] args) {
launch(args);
}
}
Is there anyway to make a Label text selectable in JavaFx8? I know, there are other simple workaround like using a TextField. But my label needs multiline text with wrapping facility which TextField does not provide. If I use TextArea, the problem is I can't shrink the TextArea based on the text's size like a Label. So I can't use either of them.
Also my use of label text is like below:
<VBox>
<Label wrapText="true"
VBox.vgrow="ALWAYS"
maxHeight="Infinity" minHeight="-Infinity"
text="Some Random Subject Line With Very Large Text To Test The Wrap Text, Lorem Ipsum Dolor"/>
</VBox>
Depending on the VBox width, Label's height resizes to fit the text fully. I can't emulate this kind of behaviour using either TextArea or TextField. But I need to be able to select the text from Label. Any ideas?
Here is a workaround until someone post something better.
If you double click the label it changes to a TextArea. You can then copy the text. Once you press enter on the TextArea it changes back to the label.
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextArea;
import javafx.scene.input.MouseButton;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.Priority;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
/**
*
* #author blj0011
*/
public class JavaFXApplication110 extends Application
{
#Override
public void start(Stage primaryStage)
{
VBox root = new VBox();
StackPane stackpane = new StackPane();
Label label = new Label("Hello world Hello world Hello world Hello world Hello world Hello world Hello world Hello world Hello world");
VBox.setVgrow(label, Priority.ALWAYS);
label.wrapTextProperty().set(true);
label.setOnMouseClicked(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent mouseEvent) {
if(mouseEvent.getButton().equals(MouseButton.PRIMARY)){
if(mouseEvent.getClickCount() == 2){
label.setVisible(false);
TextArea textarea = new TextArea(label.getText());
textarea.setPrefHeight(label.getHeight() + 10);
stackpane.getChildren().add(textarea);
textarea.setOnKeyPressed(event ->{
System.out.println(event.getCode());
if(event.getCode().toString().equals("ENTER"))
{
stackpane.getChildren().remove(textarea);
label.setVisible(true);
}
});
}
}
}
});
stackpane.getChildren().add(label);
root.getChildren().add(stackpane);
Scene scene = new Scene(root, 300, 250);
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
}
/**
* #param args the command line arguments
*/
public static void main(String[] args)
{
launch(args);
}
}
This above picture is result of my code.But I want like the following.
How can I fix it? The following is my code.I read too many sources but they was too complicated. For example,a source that I read, I think this way is very complicated.Maybe there is a easy way to solve this problem.
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
public class Test extends Application {
public BorderPane border = new BorderPane();
public Label name = new Label("Name");
public Label surname = new Label("Surname");
public TextField name1 = new TextField();
public TextField surname1 = new TextField();
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage arg0) throws Exception {
Scene scene = new Scene(new VBox(), 300, 200);
arg0.setTitle("Header");
arg0.setResizable(false);
scene.setFill(Color.OLDLACE);
StackPane grid = addStackPane();
border.setMargin(grid, new Insets(12,12,12,12));
border.setCenter(grid);
((VBox) scene.getRoot()).getChildren().add(border);
arg0.setScene(scene);
arg0.show();
}
#SuppressWarnings("static-access")
public StackPane addStackPane() {
StackPane pane = new StackPane();
GridPane grid = new GridPane();
Label title = new Label("Border Title");
title.setStyle("-fx-translate-y: -7");
pane.setAlignment(title, Pos.TOP_LEFT);
grid.setStyle("-fx-content-display: top");
grid.setStyle("-fx-border-insets: 20 15 15 15");
grid.setStyle("-fx-background-color: white");
grid.setStyle("-fx-border-color: black");
grid.setHgap(10);
grid.setVgap(10);
grid.setPadding(new Insets(25, 10, 25, 10));
grid.add(name, 1, 0);
grid.add(name1, 2, 0);
grid.add(surname, 1, 1);
grid.add(surname1, 2, 1);
pane.getChildren().addAll(grid, title);
return pane;
}
}
Thank you all that reads this topic.
Try to set -fx-background-color of your title label to the same color as the borderPane's background. And make sure you set in a css file, because it's not possible to set multiple styles via setStyle() unless you concatenate them:
myComponent.setStyle("-fx-text-fill: white;"+
"-fx-background-color: black;");
Furthermore it is bad practice to use an InlineStyleSheets as it always has a higher priority than a rule specified in a CSS StyleSheet.
(If you change pane.setAlignment(title, Pos.TOP_LEFT) to StackPane.setAlignment(title, Pos.TOP_LEFT) you can remove the "static-acces" warning.)
User jewelsea has made a control to perform this.
The related stackoverflow question is: How to add border to panel of javafx?
And on gitHub: https://gist.github.com/jewelsea/2838292
I have used it with minimal modification and it works like a charm.
My css code for it looks like this yet it still doesn't work. scrollpane?
.scroll-pane:corner > .viewport {
-fx-background-color : #191A19;
}
Is there a problem with my syntax or does the whole view port issue not allow me to edit any other aspect of the
You css selector is wrong.
.scroll-pane:corner
selects Nodes with class "scroll-pane" which have a pseudo-class state "corner" activated. According to the css documentation, scroll pane has no "corner" pseudoclass.
.scroll-pane:corner > .viewport
would select a node with class "viewport" that had an (immediate) parent node with class "scroll-pane" and with that parent node having the pseudoclass state "corner" activated. So, if anything, you would be selecting the viewport here.
The css you need is
.scroll-pane > .corner {
-fx-background-color: #191A19 ;
}
Maybe have a look at a general purpose tutorial on css selectors, such as the one at w3schools
Update complete example:
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.ScrollPane.ScrollBarPolicy;
import javafx.scene.control.TextArea;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
public class ScrollPaneStyledCorner extends Application {
#Override
public void start(Stage primaryStage) {
BorderPane root = new BorderPane();
ScrollPane scrollPane = new ScrollPane();
scrollPane.setPrefHeight(200);
scrollPane.setPrefWidth(200);
TextArea textArea = new TextArea(System.getProperty("javafx.version"));
scrollPane.setContent(textArea);
scrollPane.setVbarPolicy(ScrollBarPolicy.ALWAYS);
scrollPane.setHbarPolicy(ScrollBarPolicy.ALWAYS);
root.setCenter(scrollPane);
Scene scene = new Scene(root);
scene.getStylesheets().add(getClass().getResource("scrollPaneCorner.css").toExternalForm());
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
scrollPaneCorner.css:
.scroll-pane > .corner {
-fx-background-color: #191A19 ;
}
It works :
.corner {
-fx-background-color: #363636 ;
}