JavaFX Text message not displayed - javafx

stage = primaryStage;
Text message = new Text();
pane1 = new GridPane();
pane1.add(message, 0, 0);
scene1 = new Scene(pane1);
//scene2 is built and similar to scene.
if (getAns() == false) {
message.setText("Wrong");
stage.setScene(scene1);
} else {
message.setText("Correct");
stage.setScene(scene2);
}
stage.setTitle("Test");
stage.show();
When getAns() is true, message is displayed. When getAns() is false, message is not displayed, why?

message is displayed in scene1. So if you display scene2, you can't see it. (It can't be in two different scenes.) – James_D Oct 4 at 15:41

Related

JavaFX custom dialog set Layout of node

We created a Custom Dialog without an FXML file. We are using JavaFX 8.
The dialog loads and functions as expected but we can not move the Buttons and the TextField to enhance the styling.
We have tried to use tf.setLayoutY(50) this has no effect.
We used this tf.setPromptText("This Works ?") and it works.
We would rather not use css to accomplish this styling.
And we will consider a FXML file if we can keep the two event handlers that force data to be entered in the TextField.
So the question is: How to style this Custom Dialog?
The code is a mess as it includes some concepts we tried:
public void CustomDialog() {
Dialog dialog = new Dialog<>();
dialog.setResizable(false);
final Window window = dialog.getDialogPane().getScene().getWindow();
stage = (Stage) window;
stage.setMinHeight(600);
stage.setMinWidth(400);
TextField tf = new TextField();
tf.setLayoutX(10);
tf.setLayoutY(50);
dialog.getDialogPane().getButtonTypes().addAll(ButtonType.OK, ButtonType.CANCEL);
dialog.getDialogPane().getChildren().add(tf);
dialog.getDialogPane().setContent(tf);
// Create an event filter that consumes the action if the text is empty
EventHandler<ActionEvent> filter = event -> {
if (tf.getText().isEmpty()) {
event.consume();
}
};
// lookup the buttons
ButtonBase okButton = (Button) dialog.getDialogPane().lookupButton(ButtonType.OK);
Button cancelButton = (Button) dialog.getDialogPane().lookupButton(ButtonType.CANCEL);
// add the event-filter
okButton.addEventFilter(ActionEvent.ACTION, filter);
cancelButton.addEventFilter(ActionEvent.ACTION, filter);
stage.setOnCloseRequest(event -> {
if (tf.getText().isEmpty()) {
event.consume();
}
}
//Scene scene = new Scene(root);
//dialogStage.setScene(scene);
dialog.initModality(Modality.APPLICATION_MODAL);
//dialogStage.setAlwaysOnTop(true);
//dialogStage.setResizable(false);
tf.setPromptText("This Works ?");
tf.requestFocus();// This does not work
dialog.showAndWait();
}
Grendel we enhanced your answer so anyone who comes by and sees the code you posted in your question will understand as you said it was a mess
Your posted answer was real old school but less work perhaps than building a FXML file
Besides it is good to know some old school tricks
public void NewDialog(){
Label lblAmt = new Label("Enter Amount");
Button btnOK = new Button("OK");
TextField txtAmt = new TextField();
AnchorPane secondaryLayout = new AnchorPane();
secondaryLayout.setStyle("-fx-border-color:red;-fx-border-width:10px; -fx-background-color: lightblue;");
secondaryLayout.getChildren().addAll(lblAmt,btnOK,txtAmt);
lblAmt.setLayoutX(30);
lblAmt.setLayoutY(30);
txtAmt.setLayoutX(164);
txtAmt.setLayoutY(25);
txtAmt.setMaxWidth(116);
btnOK.setLayoutX(190);
btnOK.setLayoutY(100);
btnOK.setStyle("-fx-font-size: 18px;-fx-font-weight: bold;");
lblAmt.setStyle("-fx-font-size: 18px;-fx-font-weight: bold;");
txtAmt.setStyle("-fx-font-size: 18px;-fx-font-weight: bold;");
Scene secondScene = new Scene(secondaryLayout, 300, 180);
EventHandler<ActionEvent> filter = event -> {
if(txtAmt.getText().isEmpty()) {
event.consume();
}
};
// New window (Stage)
Stage newWindow = new Stage();
newWindow.initStyle(StageStyle.UNDECORATED);
//newWindow.initModality(Modality.APPLICATION_MODAL);
newWindow.setResizable(false);
newWindow.setTitle("Second Stage");
newWindow.setScene(secondScene);
btnOK.addEventHandler(ActionEvent.ACTION,filter);
btnOK.setOnAction(evt -> {
String str = txtAmt.getText();
System.out.println("################ str "+str);
if(txtAmt.getText().equals("")) {
evt.consume();
txtAmt.requestFocus();
}else{
newWindow.close();
}
});
newWindow.setOnCloseRequest(event -> {
if(txtAmt.getText().isEmpty()) {
event.consume();
}
});
txtAmt.requestFocus();
newWindow.showAndWait();
}

javafx - Navigation Sidebar with Toggle

So in windows 10 you have the windows menu with the icons on the left side:
When clicking on the hamburger icon the menu expands and text is show.
The expanded part is overlaying the content. The text is showing. and it was animated in (sliding transition).
In my application I want to make a similar menu on the right side (see blue part):
I have absolutely no idea how to get this effect. Currently I made a button with a graphic. I only display the graphic and when I click on the hamburger I show all the text by changing the setContentDisplay(ContentDisplay.GRAPHIC_ONLY) to setContentDisplay(ContentDisplay.RIGHT) 2 things that are wrong with this approach.
it pushes the content.
You cannot add a transition.
Any help would be appreciated, especially examples.
Demo
I made a demo that shows what I currently have:
public class Main extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) {
BorderPane root = new BorderPane();
JFXButton[] jfxButtons = {
new JFXButton("Some text", new FontAwesomeIconView(FontAwesomeIcon.LINK)),
new JFXButton("Some text", new FontAwesomeIconView(FontAwesomeIcon.LINK)),
new JFXButton("Some text", new FontAwesomeIconView(FontAwesomeIcon.LINK)),
};
JFXHamburger hamburger = new JFXHamburger();
HamburgerNextArrowBasicTransition transition = new HamburgerNextArrowBasicTransition(hamburger);
transition.setRate(-1);
hamburger.setAlignment(Pos.CENTER_RIGHT);
hamburger.setPadding(new Insets(5));
hamburger.setStyle("-fx-background-color: #fff;");
hamburger.setOnMouseClicked(event -> {
transition.setRate(transition.getRate() * -1);
transition.play();
if (transition.getRate() == -1) {
for (JFXButton jfxButton : jfxButtons) {
jfxButton.setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
}
} else {
for (JFXButton jfxButton : jfxButtons) {
jfxButton.setContentDisplay(ContentDisplay.RIGHT);
}
}
});
ScrollPane scrollPane = new ScrollPane();
VBox vBox = new VBox();
scrollPane.setContent(vBox);
vBox.getStyleClass().add("content_scene_right");
vBox.getChildren().add(hamburger);
vBox.getChildren().addAll(jfxButtons);
for (JFXButton jfxButton : jfxButtons) {
jfxButton.setMaxWidth(Double.MAX_VALUE);
jfxButton.setRipplerFill(Color.valueOf("#40E0D0"));
VBox.setVgrow(jfxButton, Priority.ALWAYS);
jfxButton.setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
}
vBox.setFillWidth(true);
Label labelHoverOverTest = new Label("Testing label");
VBox vbox2 = new VBox();
vbox2.getChildren().addAll(labelHoverOverTest);
vbox2.setAlignment(Pos.CENTER_RIGHT);
root.setRight(scrollPane);
root.setCenter(vbox2);
Scene scene = new Scene(root);
primaryStage.setMinWidth(400);
primaryStage.setMinHeight(400);
primaryStage.setScene(scene);
primaryStage.show();
}
}
I used JFoenix and fontawesomefx for this demo, but it can also be javafx scene buttons with any graphic.
Here are some images of what the demo looks like:
As you can see it pushes it the content in the center and I can't add any transition.
(here is a sample from bootstrap to give you an idea on What I'm trying to make it look like 1: https://bootsnipp.com/snippets/Pa9xl, 2: https://bootsnipp.com/snippets/featured/navigation-sidebar-with-toggle (with this one the content still moves, but it should give you a clear idea on what my vision is))
Problem is that you are using BorderPane and placing everything on same layer, so when content on right changes width it will affect one in the center and such.
In other to avoid this you should make it layered, so for root of view use StackPane, this pane should have 2 children, 1 for main content and 1 for sidebar, make sure that sidebar is above main content, now this 2 can be any Pane that you want. This way sidebar will be placed over main content and it won't push content.
Using code you provided and just adding StackPane you get something like this:
#Override
public void start(Stage primaryStage) {
StackPane root = new StackPane();
BorderPane mainContent = new BorderPane();
BorderPane sidebar = new BorderPane();
JFXButton[] jfxButtons = {
new JFXButton("Some text", new FontAwesomeIconView(FontAwesomeIcon.LINK)),
new JFXButton("Some text", new FontAwesomeIconView(FontAwesomeIcon.LINK)),
new JFXButton("Some text", new FontAwesomeIconView(FontAwesomeIcon.LINK)),};
JFXHamburger hamburger = new JFXHamburger();
HamburgerNextArrowBasicTransition transition = new HamburgerNextArrowBasicTransition(hamburger);
transition.setRate(-1);
hamburger.setAlignment(Pos.CENTER_RIGHT);
hamburger.setPadding(new Insets(5));
hamburger.setStyle("-fx-background-color: #fff;");
hamburger.setOnMouseClicked(event -> {
transition.setRate(transition.getRate() * -1);
transition.play();
if (transition.getRate() == -1) {
for (JFXButton jfxButton : jfxButtons) {
jfxButton.setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
}
} else {
for (JFXButton jfxButton : jfxButtons) {
jfxButton.setContentDisplay(ContentDisplay.RIGHT);
}
}
});
ScrollPane scrollPane = new ScrollPane();
VBox vBox = new VBox();
scrollPane.setContent(vBox);
vBox.getStyleClass().add("content_scene_right");
vBox.getChildren().add(hamburger);
vBox.getChildren().addAll(jfxButtons);
for (JFXButton jfxButton : jfxButtons) {
jfxButton.setMaxWidth(Double.MAX_VALUE);
jfxButton.setRipplerFill(Color.valueOf("#40E0D0"));
VBox.setVgrow(jfxButton, Priority.ALWAYS);
jfxButton.setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
}
vBox.setFillWidth(true);
Label labelHoverOverTest = new Label("Testing label");
VBox vbox2 = new VBox();
vbox2.getChildren().addAll(labelHoverOverTest);
vbox2.setAlignment(Pos.CENTER_RIGHT);
mainContent.setCenter(vbox2);
sidebar.setRight(scrollPane);
root.getChildren().addAll(mainContent, sidebar);
Scene scene = new Scene(root);
primaryStage.setMinWidth(400);
primaryStage.setMinHeight(400);
primaryStage.setScene(scene);
primaryStage.show();
}
As for transition I'm not sure what is problem there, for me it works fine.

Image not displayed in ImageView: JavaFX

Below is the code I use to view image and caption text together:
try
{
Scanner scanner = new Scanner( new File("data.txt") );
String text = scanner.useDelimiter("ENDOFFILE").next();
scanner.close(); // Put this call in a finally block
System.out.println(text);
String[] data = text.split("\n");
for(int i=0;i<data.length;i++)
{
if(i%2==0)
{
System.out.println("This is "+data[i]);
Image img = new Image(new File(data[i]).toURI().toString(), 100, 0, false, false);
ImageView selectedImage = new ImageView();
selectedImage.setImage(img);
v.getChildren().addAll(selectedImage);
}
else
{
Text t = new Text(data[i]);
t.setFont(Font.font("Tahoma", FontWeight.NORMAL, 14));
v.getChildren().add(t);
}
}
}
catch(Exception E)
{
E.printStackTrace();
}
root2.getChildren().add(v);
Scene scene = new Scene(root2, 1000, 1000);
stage.setScene(scene);
stage.show();
}
data[i] for the image is Udiagram.jpg which is present within the same directory as the program. No exceptions occur but the image is not displayed, it shows empty with only text shown as follows: Text goes here.
The file data.txt is as follows:
UDiagram.jpg
Hit and Run
ENDOFFILE
What could be the reason for not displaying the image but only the text?
I believe you just need to concatenate the file and folder name to the beginning of your String.
Image image = new Image("file:FOLDER_NAME/imageName.gif");
ImageView imageView = new ImageView();
imageView.setImage(image);
imageView.setFitWidth(100);
imageView.setPreserveRatio(true);
imageView.setSmooth(true);

JavaFX ScrollPane PannableProperty with TitledPane

I'm building a GUI application with javafx that needs PannableProperty from the ScrollPane to work when the user drag the content of it from anywhere.
In oracle docs they say about the "pannableProperty":
Specifies whether the user should be able to pan the viewport by using
the mouse. If mouse events reach the ScrollPane (that is, if mouse
events are not blocked by the contained node or one of its children)
then pannable is consulted to determine if the events should be used
for panning.
So my problem is the mouse event cannot reach the ScrollPane..
Anyone has a clue how to make it possible?
this is a simple code to test it:
ScrollPane root = new ScrollPane();
root.setHbarPolicy(ScrollPane.ScrollBarPolicy.ALWAYS);
root.setVbarPolicy(ScrollPane.ScrollBarPolicy.ALWAYS);
root.setPannable(true);
VBox v = new VBox(10);
TitledPane c1 = new TitledPane("test: ", new HBox(new Label("test: "), new TextField()));
HBox c2 = new HBox(new Label("we are just in HBox "), new TextField());
Label c3 = new Label("I'm just a label and pannableProperty works here");
TitledPane c4 = new TitledPane("test4", new HBox(new Label("test: "), new TextField()));
AnchorPane c5 = new AnchorPane();
c5.setPrefSize(100, 100);
v.getChildren().addAll(c1, c2, c3, c4, c5);
root.setContent(v);
Scene scene = new Scene(root, 300, 300);
primaryStage.setScene(scene);
primaryStage.show();
Another tricky one :-)
The default Skin implementation of the TitledPane is a subclass of SkinBase and the default constructor (which gets invoked by TitledPaneSkin) does this (shortened version):
protected SkinBase(final C control) {
// Default behavior for controls is to consume all mouse events
consumeMouseEvents(true);
}
So we need to reverse this, unfortunately you have to do reflection for this:
TitledPane c1 = new TitledPane("test: ", new HBox(new Label("test: "), new TextField()));
c1.skinProperty().addListener((w,o,n)-> {
if(n instanceof SkinBase) {
SkinBase<?> skinbase = (SkinBase<?>) n;
try {
Method m = SkinBase.class.getDeclaredMethod("consumeMouseEvents", Boolean.TYPE);
AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
boolean wasAccessible = m.isAccessible();
try {
m.setAccessible(true);
m.invoke(skinbase, false);
return null;
}
catch(ReflectiveOperationException e) { throw new IllegalStateException(e); }
finally {
m.setAccessible(wasAccessible);
}
});
} catch (ReflectiveOperationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
And now it should work, at least it does in my test application.
EDIT #1:
Doing this resets the focus during mouse operations, which renders the TitledPane somewhat unusable. So we are now messing with the focus system:
ScrollPane root = new ScrollPane();
root.setFocusTraversable(false);
Scene scene = new Scene(root, 300, 300);
scene.focusOwnerProperty().addListener((w,o,n)->
if(n == root && o != null) {
o.requestFocus();
}
});
Basically what we are doing here is that we re-focus the previously focussed component if the newly focused element is the ScrollPane.

Make portion of a text bold in a JavaFx Label or Text

In my JavaFx application I need to have a word or two rendered in boldface in the whole sentence. Currently the sentence is rendered as a JavaFx Label but upgrading component also would not allow me set the text as so that I can have the words "Sample" displayed in bold.
String s = "This is a <b>Sample</b> sentence"
Label label = new Label(s);
output
This is a Sample sentence
JavaFx Text also does not allow this. Is there any component where I can have a portion of the text in boldface?
I am not sure if JavaFx WebView is a good idea for rendering many small sentences in a window.
It is possible to use TextFlow container from JavaFX8.
Then you can easily add differently styled Text nodes inside it.
TextFlow flow = new TextFlow();
Text text1=new Text("Some Text");
text1.setStyle("-fx-font-weight: bold");
Text text2=new Text("Some Text");
text2.setStyle("-fx-font-weight: regular");
flow.getChildren().addAll(text1, text2);
TextFlow container will automatically wrap content Text nodes.
Since the previous answers did not include FXML code, I'll post an additional one.
As suggested by #Ernisto, you can use a TextFlow that contains Text parts, where each part can be styled differently.
Example FXML file content:
<TextFlow>
<Text text="Normal text and "/>
<Text text="bold text and " style="-fx-font-weight: bold"/>
<Text text="italic text and " style="-fx-font-style: italic"/>
<Text text="red text." style="-fx-stroke: red"/>
</TextFlow>
Output:
Update: JavaFX 8 provides new control for the rich text: TextFlow
Unfortunately there is no such feature in 2.2, although it may be included into next release.
For now you can try to use next approaches:
HBox with several Label or Text components
WebView
Canvas with several Text components drawn
public class UtilsDialog {
private static final String TAG = "UtilsDialog";
private static boolean sIsShowing = false;
public static void showDialogShowError(String title, String msg, String defaultStyle,
#Nullable String customStyle, String... styledWords) {
if (sIsShowing) return;
Stage dialogStage = new Stage(StageStyle.UTILITY);
dialogStage.initModality(Modality.APPLICATION_MODAL);
dialogStage.setWidth(400);
dialogStage.setHeight(220);
BorderPane borderPane = new BorderPane();
borderPane.setPadding(new Insets(15));
borderPane.setPrefWidth(Integer.MAX_VALUE);
borderPane.setPrefHeight(Integer.MAX_VALUE);
Scene scene = new Scene(borderPane);
dialogStage.setScene(scene);
sIsShowing = true;
dialogStage.show();
UtilsGui.closeOnEsc(borderPane, scene);
scene.addEventHandler(KeyEvent.KEY_PRESSED, t -> {
if (t.getCode() == KeyCode.ESCAPE) {
sIsShowing = false;
}
});
// Top
Text textTitle = new Text(title);
textTitle.setStyle("-fx-font-size: 18px;");
HBox hBoxTop = new HBox(10);
hBoxTop.getChildren().addAll(textTitle);
borderPane.setTop(hBoxTop);
// Center
TextFlow textFlow = new TextFlow();
List<String> words = Arrays.asList(msg.split(" "));
List<String> styledWordsList = Arrays.asList(styledWords);
for (String word : words) {
Text tmpWord = new Text(word);
if (styledWordsList.contains(word
.replace(".", "")
.replace(",", "")
.replace("?", "")
.replace("!", "")
.replace(";", "")
.replace("\n", "")
)) {
tmpWord.setStyle(customStyle);
} else {
if (defaultStyle == null) {
tmpWord.setStyle("");
} else {
tmpWord.setStyle(defaultStyle);
}
}
tmpWord.setText(tmpWord.getText());
textFlow.getChildren().add(tmpWord);
textFlow.getChildren().add(new Text(" "));
}
Text textMsg = new Text(msg);
textMsg.setStyle("-fx-font-size: 14px;");
HBox hBoxInputPane = new HBox(10);
hBoxInputPane.setAlignment(Pos.CENTER);
VBox vBoxCenter = new VBox(10);
vBoxCenter.setPadding(new Insets(25, 0, 15, 0));
vBoxCenter.getChildren().addAll(textFlow);
borderPane.setCenter(vBoxCenter);
JFXButton btnOk = new JFXButton("OK");
btnOk.setAlignment(Pos.CENTER_RIGHT);
btnOk.setStyle("-fx-text-fill: WHITE; -fx-background-color: #5264AE; -fx-font-size: 14px;");
btnOk.setOnAction(event -> {
sIsShowing = false;
dialogStage.close();
});
// Bottom
HBox hBoxBottom = new HBox();
final Pane spacer = new Pane();
HBox.setHgrow(spacer, Priority.ALWAYS);
hBoxBottom.getChildren().addAll(spacer, btnOk);
borderPane.setBottom(hBoxBottom);
// store on close
dialogStage.setOnCloseRequest(event -> sIsShowing = false);
}
}
call:
UtilsDialog.showDialogShowError("Test", "This is the message to show. Does it work?",
null, "-fx-font-weight: bold", "This", "message", "show");

Resources