I have tests about KeyEvent in javafx,if I use onKeyPressed() method bound to any kind of pane,it wouldn't work.bound to scene or a button would work fine.I am wondering how can I let pane associated with KeyEvent.
To add key events handlers to pane effectively you need to request focus on pane first.
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.HBox;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class PanesKeyEventsApp extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage stage) throws Exception {
StackPane stackPane1 = new StackPane();
stackPane1.setPrefSize(200, 200);
stackPane1.setStyle("-fx-background-color: purple;");
StackPane stackPane2 = new StackPane();
stackPane2.setPrefSize(200, 200);
stackPane2.setStyle("-fx-background-color: yellow;");
HBox hBox = new HBox(stackPane1, stackPane2);
Scene scene = new Scene(hBox);
stage.setScene(scene);
stage.show();
stackPane1.setOnMouseClicked(event -> stackPane1.requestFocus());
stackPane2.setOnMouseClicked(event -> stackPane2.requestFocus());
stackPane1.addEventHandler(KeyEvent.KEY_PRESSED, event -> System.out.println("purple key pressed " + event.getCode()));
stackPane2.addEventHandler(KeyEvent.KEY_PRESSED, event -> System.out.println("yellow key pressed " + event.getCode()));
}
}
Related
I want to be able to always show the popup part of a combobox regardless of the fact it has been clicked or not, or even without the combo being focused. I tried to use the show() method of the combo, but in my case the popup part never shows.
My code is:
import javafx.application.Platform;
import javafx.collections.ObservableList;
import javafx.embed.swing.JFXPanel;
import javafx.scene.Scene;
import javafx.scene.control.ComboBox;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;
public class ComBoBoxTest {
public static final void main(String[] args) {
ComBoBoxTest test = new ComBoBoxTest();
test.setup();
}
private void setup() {
new JFXPanel();
Platform.runLater(new Runnable() {
#Override
public void run() {
createUI();
}
});
}
private void createUI() {
Stage stage = new Stage();
Pane pane = new Pane();
ComboBox<String> combo = new ComboBox();
ObservableList<String> values = combo.getItems();
values.add("ONE");
values.add("TWO");
values.add("THREE");
combo.setVisibleRowCount(3);
combo.show();
pane.getChildren().add(combo);
Scene scene = new Scene(pane);
stage.setScene(scene);
stage.show(); // the important part
}
}
In that case, I thought that my show() method would force to open the popup, but the result is that the popup is never shown
Per the excellent comment of kleopatra, the solution is to call show() on the Combo after the Stage is shown. This example works:
import javafx.application.Platform;
import javafx.collections.ObservableList;
import javafx.embed.swing.JFXPanel;
import javafx.scene.Scene;
import javafx.scene.control.ComboBox;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;
public class ComBoBoxTest {
public static final void main(String[] args) {
ComBoBoxTest test = new ComBoBoxTest();
test.setup();
}
private void setup() {
new JFXPanel();
Platform.runLater(new Runnable() {
#Override
public void run() {
createUI();
}
});
}
private void createUI() {
Stage stage = new Stage();
Pane pane = new Pane();
ComboBox<String> combo = new ComboBox();
ObservableList<String> values = combo.getItems();
values.add("ONE");
values.add("TWO");
values.add("THREE");
combo.setVisibleRowCount(3);
pane.getChildren().add(combo);
Scene scene = new Scene(pane);
stage.setScene(scene);
stage.show();
combo.show(); // call show() on the Combo after the stage is shown
}
}
How to do that in JavaFX?
The popup shows up when the mouse enters a node. When the mouse enters the showing popup, the popup obscures the mouse from the node. Then the node fire exit event. How to make the popup ignore the mouse events?
code
package sample;
import javafx.application.Application;
import javafx.geometry.Point3D;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.StackPane;
import javafx.stage.Popup;
import javafx.stage.Stage;
public class Main extends Application {
#Override
public void start(Stage primaryStage) {
StackPane root = new StackPane();
primaryStage.setScene(new Scene(root, 300, 275));
Label labelNode = new Label("Label Node");
labelNode.setPrefHeight(200);
labelNode.styleProperty().set("-fx-background-color: orange");
Popup popup = new Popup();
popup.getScene().getRoot().setMouseTransparent(true);
AnchorPane popContent =new AnchorPane();
popContent.styleProperty().set("-fx-background-color: red");
popContent.setPrefHeight(100);
popContent.getChildren().add(new Label("Popup content"));
popup.getContent().add(popContent);
labelNode.setOnMouseEntered(event->{
Point3D point3D = labelNode.localToScene(event.getX(), event.getY(), 0);
popup.show(primaryStage, point3D.getX()-5, point3D.getY()-5);
});
labelNode.setOnMouseExited(event->{
popup.hide();
});
root.getChildren().add(labelNode);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Please try moving the cursor in to "yellow" several times.
Solution:
Keep two boolean nodeExited and popupExited statuses. Hide popup when both are true.
package sample;
import javafx.application.Application;
import javafx.geometry.Point3D;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.StackPane;
import javafx.stage.Popup;
import javafx.stage.Stage;
public class Main extends Application {
boolean nodeExited = false;
boolean popupExited = false;
#Override
public void start(Stage primaryStage) {
StackPane root = new StackPane();
primaryStage.setScene(new Scene(root, 300, 275));
Label labelNode = new Label("Label Node");
labelNode.setPrefHeight(200);
labelNode.styleProperty().set("-fx-background-color: orange");
Popup popup = new Popup();
popup.getScene().getRoot().setMouseTransparent(true);
AnchorPane popContent = new AnchorPane();
popContent.styleProperty().set("-fx-background-color: red");
popContent.setPrefHeight(100);
popContent.getChildren().add(new Label("Popup content"));
popup.getContent().add(popContent);
popup.getScene().setOnMouseEntered(event -> {
popupExited = false;
});
popup.getScene().setOnMouseExited(event -> {
popupExited = true;
if (nodeExited)
popup.hide();
});
labelNode.setOnMouseEntered(event -> {
nodeExited = false;
Point3D point3D = labelNode.localToScene(event.getX(), event.getY(), 0);
popup.show(primaryStage, point3D.getX() - 5, point3D.getY() - 5);
});
labelNode.setOnMouseExited(event -> {
nodeExited = true;
if (popupExited)
popup.hide();
});
root.getChildren().add(labelNode);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
I have a TextField with a listener that is triggered every time I select a portion of text it contains. For example, in the following situation, after selecting the two digits on the left I replaced by 5:
This works properly, but this one not:
The error is:
Exception in thread "JavaFX Application Thread"
java.lang.StringIndexOutOfBoundsException: String index out of range: 3
The code is:
import javafx.application.Application;
import javafx.beans.value.ObservableValue;
import javafx.scene.Scene;
import javafx.scene.control.TextField;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class SelectedText extends Application {
#Override
public void start(Stage primaryStage) {
TextField textField = new TextField();
StackPane root = new StackPane();
root.getChildren().add(textField);
Scene scene = new Scene(root, 100, 100);
primaryStage.setScene(scene);
primaryStage.show();
textField.selectedTextProperty().addListener((final ObservableValue<? extends String> ov,
final String oldSelection, final String newSelection) -> {
System.out.println ("text selected: " + newSelection);
});
}
public static void main(String[] args) {
launch(args);
}
}
I have TitledPane, which i want to hide back (after expanding - un-expand it) after pressing a button. Is there any way to do it? I didn't find any way :( Thanks!
Just do
titledPane.setExpanded(false);
Complete example:
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TitledPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class TitledPaneExample extends Application {
#Override
public void start(Stage primaryStage) {
Label label = new Label("Some content");
Button button = new Button("OK");
VBox content = new VBox(10, label, button);
TitledPane titledPane = new TitledPane("Titled Pane", content);
button.setOnAction(e -> titledPane.setExpanded(false));
VBox root = new VBox(titledPane);
Scene scene = new Scene(root, 250, 400);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
I have an internal jfxtra window. On clicking a button, I want to bring it forward.
The code that I have tried :
window w = new window("mdi win");
private Stage primaryStage;
private BorderPane rootLayout;
...
public void win() {
Parent bla = FXMLLoader.load(getClass().getResource("bla.fxml"));
w.getContentPane().getChildren().add(bla);
rootLayout.getChildren().add(w);
}
private void wfront(ActionEvent event) throws Exception {
w.isMoveToFront(); // is not?
}
How to make it possible?
So you made me curious and I went through the JFXtras docs. I came to know that Window in Jfxtras extends Control. So there is a method called toFront which can be fired on it. To show this I have created a sample for you.
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
import jfxtras.scene.control.window.Window;
public class NewWindow extends Application {
#Override
public void start(Stage primaryStage) throws Exception {
StackPane stackPane = new StackPane();
Button button = new Button("Click Me to show Window !");
Window window = new Window("Cick Me to bring me to front");
button.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
window.toFront();
window.setTitle("I am on the Front");
}
});
window.setPrefSize(200, 200);
stackPane.getChildren().addAll(window, button);
Scene scene = new Scene(stackPane, 500, 500);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Let me know, if you are looking for something else !