Auto scroll down a TextArea - java

I have a TextArea that doesn't scroll down when I add text in it. I thought using this answer, but my TextArea is connected to a StringProperty like this :
consoleTextArea.textProperty().bind(textRecu);
So the answer doesn't work for me, is there another way to make my TextArea scroll down every time I update it by the binding?

Here is fast demo of what i meant in comment about adding listener to the textRecu. Yep consoleTextArea.textProperty() can't be changed because of a binding. But textRecu has no binding => can be changed and we can add listener to it.
import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TextArea;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class Main extends Application {
private StringProperty textRecu = new SimpleStringProperty();
private TextArea consoleTextArea = new TextArea();
#Override
public void start(Stage primaryStage) throws Exception{
VBox root = new VBox();
Button button = new Button("Add some text");
button.setOnMouseClicked(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
//here you change textRecu and not consoleTextArea.textProperty()
textRecu.setValue(textRecu.getValue() +"New Line\n");
}
});
root.getChildren().addAll(consoleTextArea, button);
consoleTextArea.textProperty().bind(textRecu);
//here you also add listener to the textRecu
textRecu.addListener(new ChangeListener<Object>() {
#Override
public void changed(ObservableValue<?> observable, Object oldValue,
Object newValue) {
// from stackoverflow.com/a/30264399/1032167
// for some reason setScrollTop will not scroll properly
//consoleTextArea.setScrollTop(Double.MAX_VALUE);
consoleTextArea.selectPositionCaret(consoleTextArea.getLength());
consoleTextArea.deselect();
}
});
primaryStage.setScene(new Scene(root, 300, 275));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}

Related

why JOptionPane.showMessageDialog just working in main?

I'm using NetBeans last version and macOS. I try this is my code and JOptionPane.showMessageDialog not working. It's working if I put the syntax in the main. Please tell me why. I try vscode, and I have same problem
import javax.swing.*;
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.CheckBox;
import javafx.scene.control.Label;
import javafx.scene.control.RadioButton;
import javafx.scene.control.TextField;
import javafx.scene.control.TextInputDialog;
import javafx.scene.control.ToggleGroup;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;
public class App extends Application {
TextField txt;
public void start(Stage primaryStage) {
Label lb1 = new Label();
TextField txt = new TextField("Type here");
RadioButton rb1 = new RadioButton();
RadioButton rb2 = new RadioButton();
Button bt = new Button("click");
Button bt1 = new Button("anas aljaghbeer");
MyHandlerClass handler1 = new MyHandlerClass();
bt.setOnAction(handler1);
txt.setPrefSize(10, 10);
lb1.setText("Enter here");
txt.getText();
VBox box = new VBox();
Scene scene = new Scene(box, 1000, 1000);
box.getChildren().addAll(lb1, txt, bt);
primaryStage.setTitle("anas");
primaryStage.setScene(scene);
primaryStage.show();
}
class MyHandlerClass implements EventHandler<ActionEvent> {
#Override
public void handle(ActionEvent e) {
JOptionPane.showMessageDialog(null, " Hello");
}
}
public static void main(String[] args) {
Application.launch(args);
}
}
JOptionPane.showMessageDialog()…It's working if I put the syntax in the main. Please tell me why.
When you invoke JOptionPane.showMessageDialog() in main(), it executes on the initial thread. In a Swing program, you would invoke it from main() like this:
public static void main(String[] args) {
EventQueue.invokeLater(() -> {
JOptionPane.showMessageDialog(null, "Click to continue…");
…
});
}
In a JavaFX program you are well advised not to "mix Swing and JavaFX," unless you account for JavaFX-Swing Interoperability. Instead, evoke an Alert as shown here and below:
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class App extends Application {
TextField txt;
#Override
public void start(Stage primaryStage) {
Label label = new Label();
TextField text = new TextField("Type here");
Button button = new Button("Click");
MyHandlerClass handler = new MyHandlerClass();
button.setOnAction(handler);
text.setPrefSize(10, 10);
label.setText("Enter here");
text.getText();
VBox box = new VBox();
box.getChildren().addAll(label, text, button);
Scene scene = new Scene(box, 320, 240);
primaryStage.setScene(scene);
primaryStage.setTitle("anas");
primaryStage.show();
}
class MyHandlerClass implements EventHandler<ActionEvent> {
#Override
public void handle(ActionEvent e) {
Alert alert = new Alert(Alert.AlertType.INFORMATION, "You clicked the button.");
alert.showAndWait();
}
}
public static void main(String[] args) {
Application.launch(args);
}
}

JavaFX disable tab navigation

I am writing a console application and I would like to autocomplete commands when pressing tab. The problem is that when you press tab in javaFX it switches focus to another element in the application. Any way to disable this?
Add an event filter and consume the event:
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.TextField;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class DisableFocusNavigation extends Application {
private TextField createTextField() {
TextField textField = new TextField();
textField.addEventFilter(KeyEvent.KEY_PRESSED, event -> {
if (event.getCode() == KeyCode.TAB) {
System.out.println("Tab pressed");
event.consume();
}
});
return textField ;
}
#Override
public void start(Stage primaryStage) {
TextField tf1 = createTextField();
TextField tf2 = createTextField();
VBox root = new VBox(5, tf1, tf2);
root.setAlignment(Pos.CENTER);
root.setPadding(new Insets(20));
primaryStage.setScene(new Scene(root));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Note that this isn't particularly good practice, as it makes it impossible to use the application without a mouse (or similar input device). You should at least check for modifier keys in the event filter, and allow for some focus traversal options.

Focus Traversable on CustomMenuItem. Content loose focus on mouse hover

look at this simple app :
Press ctrl+space on the text field the listView appear with the focus and you can select with Arrow key. but if you move the mouse over the listView the customMenuItem got the hover highlight and the listview loose focus the Arrow key doesn't work anymore
How can i keep focus on the listview ??
import java.util.ArrayList;
import java.util.List;
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.geometry.Side;
import javafx.scene.Scene;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.CustomMenuItem;
import javafx.scene.control.ListView;
import javafx.scene.control.TextField;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
public class Main extends Application {
#Override
public void start(Stage primaryStage) {
try {
HBox root = new HBox(new SuggestionTextFiedl());
Scene scene = new Scene(root, 400, 400);
scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
primaryStage.setScene(scene);
primaryStage.show();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
public class SuggestionTextFiedl extends TextField {
ListView<String> lv = new ListView<>();
CustomMenuItem lvContainer = new CustomMenuItem(lv);
ContextMenu contextMenu = new ContextMenu(lvContainer);
public SuggestionTextFiedl() {
super();
List<String> content = new ArrayList<>();
content.add("item1");
content.add("item2");
content.add("item3");
content.add("item1");
content.add("item2");
content.add("item3");
lv.setItems(FXCollections.observableList(content));
lv.setPrefWidth(100);
lv.setPrefHeight(100);
this.addEventHandler(KeyEvent.KEY_RELEASED, e -> {
if (e.getCode().equals(KeyCode.SPACE) && e.isControlDown()) {
System.out.println("ici");
contextMenu.show(SuggestionTextFiedl.this, Side.BOTTOM, 0, 0);
lv.requestFocus();
}
});
}
}
}
My solution not sure that is the right way
contextMenu.addEventFilter(MouseEvent.MOUSE_ENTERED_TARGET, e -> {
e.consume();
});

I want to add items seperate from a ListView

Newbie question. I'm trying to make a javafx to do list class but i need to add a button and textfield to insert data to the listview. I want to add these but I can't add them directly to the listview. I dunno how to do it.
package learning;
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ListView;
import javafx.scene.control.TextField;
import javafx.stage.Stage;
public class ToDoList extends Application{
private ObservableList<String> doList = FXCollections.observableArrayList();
private String text="";
public void start(Stage primaryStage){
primaryStage.setTitle("2DoList");
TextField userTextField = new TextField();
Button enter=new Button("Add");
enter.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent e) {
text= userTextField.getText();
doList.add(text);
userTextField.setText("");
text="";
}
});
ListView<String> root=new ListView<String>(doList);
Scene scene=new Scene(root,250,500);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}

Using a FadeTransition on a Label causes the Label to appear different at start of transition

I need either a Label or a Text for my project. I need the label so that ellipsis can be used. The problem though, is when I try to use a FadeTransition, and play it, the label gets slightly darker at the start. Here is some demo code:
package com.neonorb.test;
import javafx.animation.FadeTransition;
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.layout.BorderPane;
import javafx.stage.Stage;
import javafx.util.Duration;
import java.io.IOException;
/**
* Created by chris on 7/20/15.
*/
public class Test extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) throws IOException {
Label label = new Label("hello");
//Text label = new Text("hello);//Using Text instead of Label does not cause the weird behavior
FadeTransition fadeTransition = new FadeTransition(Duration.seconds(3), label);
fadeTransition.setFromValue(1.0);
fadeTransition.setToValue(0.0);
fadeTransition.setOnFinished(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent actionEvent) {
label.setOpacity(1.0);
}
});
Button button = new Button("play");
button.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent actionEvent) {
fadeTransition.play();
}
});
BorderPane borderPane = new BorderPane();
borderPane.setCenter(label);
borderPane.setBottom(button);
primaryStage.setScene(new Scene(borderPane));
primaryStage.show();
}
}
So I either need a fix to this problem, or a way to use ellipsis in Text. Any ideas?
Set the opacity of the label to 0.99 initially:
label.setOpacity(0.99);
Also change the code inside setOnFinished method in the same way. Then, set the starting value of the fade transition to 0.99:
fadeTransition.setFromValue(0.99);
I know this is not the solution you are looking for, but this solution prevents the label from abruptly getting darker at the start. That is because the label actually starts with that darker status.

Categories

Resources