Scene Builder (JavaFX) Button Disable Condition - java

I'm using Scene Builder 2.0 and I want to make a button be disabled by default. That is working fine, but I want to make it enabled if two booleans are set to true. In Scene Builder how do I add a condition to a button's state?
So the launchButton method below is what will happen when the button is clicked. And the booleans in the checkBox methods should be connected to Scene Builder somehow.
Thanks so much!
public void checkBox1(ActionEvent event) {
checkBox1.setDisable(true);
checkBox1Status = true;
}
public void checkBox2(ActionEvent event) {
checkBox2.setDisable(true);
checkBox2Status = true;
}
public void launchButton(ActionEvent event) throws InterruptedException {
progressBarMainMenu(event);
}

You can't do this with Scene Builder.
The tool is about generating an FXML file, that doesn't contain code logic.

Related

JavaFX KeyEvents during Drag & Drop operation

I need to know whether a certain key is down while performing a drag & drop operation.
So I tried to use setOnKeyPressed / setOnKeyReleased of a Scene with a combination of HashMap, but I have a problem with this approach:
Imagine a scenario that one drags & drops a TableView item to somewhere while holding Control down. Now if I display a dialog at the end of the drop, while still holding Control down, the setOnKeyReleased is never called with this approach... as the Dialog is the one receiving the key released event.
How could I fix this?
Hope I understand your question here is a possible solution(work with any key):
public class Main extends Application {
SimpleBooleanProperty isKeyPress = new SimpleBooleanProperty(false);
#Override
public void start(Stage primaryStage) throws Exception{
Parent window = new VBox();
((VBox) window).getChildren().add(new Label("example of small window:"));
primaryStage.setTitle("example");
Scene scene=new Scene(window);
primaryStage.setScene(scene);
primaryStage.show();
scene.setOnKeyPressed(new EventHandler<KeyEvent>() {
#Override
public void handle(KeyEvent event) {
System.out.println("Press");
isKeyPress.set(true);
Alert alert = new Alert(Alert.AlertType.INFORMATION);
alert.setTitle("Information Dialog");
alert.setHeaderText(null);
alert.setContentText("I have a great message for you!");
Scene alertScene = alert.getDialogPane().getScene();
alertScene.setOnKeyReleased(new EventHandler<KeyEvent>() {
#Override
public void handle(KeyEvent event) {
System.out.println("Released on dialog");
isKeyPress.set(false);
}
});
alert.showAndWait();
}
});
scene.setOnKeyReleased(new EventHandler<KeyEvent>() {
#Override
public void handle(KeyEvent event) {
System.out.println("Released");
isKeyPress.set(false);
}
});
}
public static void main(String[] args) {
launch(args);
}
}
output exmple:
Press
Released on dialog
From your comment the goal is to change the behavior of the drag and drop depending on whether or not Ctrl is down. When it is do a copy operation, otherwise do a move operation. You do not need to deal with KeyEvents to implement this behavior. Instead, you would determine whether to copy or move in the onDragDetected handler. The onDragDetected handler uses a MouseEvent which has methods for querying the status of modifier keys—such as isControlDown(). Using this, we can specify what transfer modes are allowed based on the modifier keys.
Node node = ...;
node.setOnDragDetected(event -> {
Dragboard board;
if (event.isControlDown()) {
board = node.startDragAndDrop(TransferMode.COPY);
} else {
board = node.startDragAndDrop(TransferMode.MOVE);
}
// add contents to Dragboard
});
Note it may be more cross-platform to use isShortcutDown().

JavaFX - Block user from changing stages without using MODAL

I have an application that looks like the following:
When a user clicks on the deck of cards, it opens up a new Stage.
This stage can be closed in one of two ways:
Right click the stage.
Click outside of the stage (it has a evenhandler for when it loses focus).
However, sometimes I NEED the user to select one or more cards from the deck using this window. I do not want to allow him to close the window until he has selected at least one card. This means I had to use MODAL to stop him from being able to access the stage underneath (My Applicaiton). The problem with MODAL is now he can never leave the window like he could before by clicking outside the stage, even when I want him to be able to. He is now only able to leave through right clicking. I could add a button but I'd really rather not.
I hope I explained my problem well enough. What would you guys recommend I do? Is there a way I could somehow block the user from going back to the previous stage without MODAL? I'm also not able to change Modality after the Stage has been shown, so that won't work.
Thanks!
The idea is to use the onCloseRequestProperty property of your pop-up Stage.
Called when there is an external request to close this Window. The
installed event handler can prevent window closing by consuming the
received event.
With this property you can interrupt the closing of the Stage if a condition (in your case at lest one card is selected) is not met by calling consume on the WindowEvent.
Note: As the documentation states: it is only valid if the request is external, so if you call the close method of the Stage, the attached listener will be not executed. As a solution rather than calling this method you can fire the WindowEvent.WINDOW_CLOSE_REQUEST event manually.
Example:
public class PopUpApp extends Application {
Stage popupStage;
Stage primaryStage;
#Override
public void start(Stage stage) {
try {
BorderPane root = new BorderPane();
Scene scene = new Scene(root, 400, 400);
primaryStage = stage;
initPopUpStage();
// When the Pop-Up stage is showing, do not handle any action on the
// main GUI
root.disableProperty().bind(popupStage.showingProperty());
Button b = new Button("Open deck");
b.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
// Add some ToggleButtons to simulate the cards
VBox vbox = new VBox();
vbox.setAlignment(Pos.CENTER);
List<ToggleButton> toggles = new ArrayList<ToggleButton>();
for (int i = 0; i < 4; i++) {
ToggleButton tb = new ToggleButton("Card " + i + 1);
toggles.add(tb);
}
vbox.getChildren().addAll(toggles);
Scene sc = new Scene(vbox, 300, 300);
popupStage.setScene(sc);
// On close request check for the condition
popupStage.setOnCloseRequest(new EventHandler<WindowEvent>() {
#Override
public void handle(WindowEvent event) {
Boolean readytoClose = false;
for (ToggleButton toggle : toggles) {
if (toggle.isSelected()) {
readytoClose = true;
break;
}
}
// Consume the event a show a dialog
if (!readytoClose) {
event.consume();
Alert alert = new Alert(AlertType.INFORMATION,
"At least one card has be to be selected!");
alert.showAndWait();
}
}
});
popupStage.show();
}
});
root.setCenter(b);
primaryStage.setScene(scene);
primaryStage.show();
} catch (Exception e) {
e.printStackTrace();
}
}
private void initPopUpStage() {
popupStage = new Stage();
popupStage.initOwner(primaryStage);
popupStage.initStyle(StageStyle.UNDECORATED);
// On focus loss, close the window
popupStage.focusedProperty().addListener(new ChangeListener<Boolean>() {
#Override
public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
// Rather than popupStage.close(); fire the event manually
if (!newValue)
popupStage.fireEvent(new WindowEvent(popupStage, WindowEvent.WINDOW_CLOSE_REQUEST));
}
});
}
public static void main(String[] args) {
launch(args);
}
}
Update:
To make the main Stage unavailable I have added this line:
root.disableProperty().bind(popupStage.showingProperty());
This will disable the root BorderPane while the pop-up stage is showing. As soon as the pop-up window closed, the main window is enabled again.

JavaFx Drag and Drop a file INTO a program

Hey there community I was wondering if is possible to create a program that allows for the user to Drag a file from anywhere on there hard drive (the desktop, documents folder, videos folder) and drop it into the window of the program.
I am creating a media player and I want to be able to play a video by dragging and dropping a MP4 into the window. Do I need to store the file in a variable, or just the location of the file into a variable. Also, it is important I keep support for cross platform.
I am using JavaFx with java 7 update 79 jdk.
Thanks in advance.
Here is a simple drag and drop example that just sets the file name and location. Drag files to it and it shows their name and location. Once you know that it should be a completely separate matter to actually play the file. It is primarily taken from Oracle's documentation: https://docs.oracle.com/javafx/2/drag_drop/jfxpub-drag_drop.htm
A minimal implementation needs two EventHandler s set OnDragOver and OnDragDropped.
public class DragAndDropTest extends Application {
#Override
public void start(Stage primaryStage) {
Label label = new Label("Drag a file to me.");
Label dropped = new Label("");
VBox dragTarget = new VBox();
dragTarget.getChildren().addAll(label,dropped);
dragTarget.setOnDragOver(new EventHandler<DragEvent>() {
#Override
public void handle(DragEvent event) {
if (event.getGestureSource() != dragTarget
&& event.getDragboard().hasFiles()) {
/* allow for both copying and moving, whatever user chooses */
event.acceptTransferModes(TransferMode.COPY_OR_MOVE);
}
event.consume();
}
});
dragTarget.setOnDragDropped(new EventHandler<DragEvent>() {
#Override
public void handle(DragEvent event) {
Dragboard db = event.getDragboard();
boolean success = false;
if (db.hasFiles()) {
dropped.setText(db.getFiles().toString());
success = true;
}
/* let the source know whether the string was successfully
* transferred and used */
event.setDropCompleted(success);
event.consume();
}
});
StackPane root = new StackPane();
root.getChildren().add(dragTarget);
Scene scene = new Scene(root, 500, 250);
primaryStage.setTitle("Drag Test");
primaryStage.setScene(scene);
primaryStage.show();
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}
When working with Drag and Drop events, you could try the following:
Obtain a Dragboard-object of the DragEvent and work with the method getFiles:
private void handleDragDropped(DragEvent event){
Dragboard db = event.getDragboard();
File file = db.getFiles().get(0);
}
I solved this by adding two event handlers. One for DragDropped event and the other for DragOver event.
e.g:
#FXML
void handleFileOverEvent(DragEvent event)
{
Dragboard db = event.getDragboard();
if (db.hasFiles())
{
event.acceptTransferModes(TransferMode.COPY);
}
else
{
event.consume();
}
}
#FXML
void handleFileDroppedEvent(DragEvent event)
{
Dragboard db = event.getDragboard();
File file = db.getFiles().get(0);
handleSelectedFile(file);
}
Else it did not work for me, dragging the file over my pane, didn't trigger anything.

javafx: How to bind the Enter key to a button and fire off an event when it is clicked?

Basically, I have a okayButton that sits in a stage and when it is clicked , it performs a list of tasks. Now I want to bind the Enter key to this button such that when it is clicked OR the ENTER key is pressed, it performs a list of tasks.
okayButton.setOnAction(e -> {
.........
}
});
How can I do that ? I have read the following post already. However, it did not help me to achieve what I want to do.
First, set a hanlder on your button :
okayButton.setOnAction(e -> {
......
});
If the button has the focus, pressing Enter will automatically call this handler. Otherwise, you can do this in your start method :
#Override
public void start(Stage primaryStage) {
// ...
Node root = ...;
setGlobalEventHandler(root);
Scene scene = new Scene(root, 0, 0);
primaryStage.setScene(scene);
primaryStage.show();
}
private void setGlobalEventHandler(Node root) {
root.addEventHandler(KeyEvent.KEY_PRESSED, ev -> {
if (ev.getCode() == KeyCode.ENTER) {
okayButton.fire();
ev.consume();
}
});
}
If you have only one button of this kind, you can use the following method instead.
okayButton.setDefaultButton(true);
You can dynamically change the default button property of the currently focused button by using binding
btn.defaultButtonProperty().bind(btn.focusedProperty());
I've had the same problem like mynameisJEFF. (I'm using Windows and as I read here: http://mail.openjdk.java.net/pipermail/openjfx-dev/2016-June/019234.html it is the SPACE_BAR and not ENTER, which fires a Button in JavaFX) I didn't want to add a listener to every Button, so I registered a Listener to the root node and asked the scene, which node is focused to fire that one. Here is my code (it is xtend, but I think it very easy to understand):
override start(Stage primaryStage) throws Exception {
val root = FXTable.createRoot
val mainScene = new Scene(root)
root.addEventHandler(KeyEvent.KEY_RELEASED, [event|
if(event.code === KeyCode.ENTER){
switch(focusedNode : mainScene.focusOwnerProperty.get){
Button:{
focusedNode.fire
event.consume
}
default:{
}
}
}
])
primaryStage.scene = mainScene
primaryStage.show
primaryStage.maximized = true
}
There is a much more simple a standard way to do that using setOnKeyPressed
okayButton.setOnKeyPressed(event -> {
if (event.getCode().equals(KeyCode.ENTER)) {
okayButton.fire();
}
}
);
And don't forget that you should define SetOnAction too, other way it's work but it's doing nothing.
okayButton.setOnAction(event -> {
// Do what ever you want to your button do. Like :
System.Out.Print("Okay Button Fired (Clicked or Pressed");
}
);
This should work:
okayButton.addKeyListener(new java.awt.event.KeyAdapter() {
public void keyPressed(java.awt.event.KeyEvent evt) {
if(evt.getKeyCode() == KeyEvent.VK_ENTER){
System.out.print("Your function call or code can go here");
}
}
});

How to close a JavaFX application on window close?

In Swing you can simply use setDefaultCloseOperation() to shut down the entire application when the window is closed.
However in JavaFX I can't find an equivalent. I have multiple windows open and I want to close the entire application if a window is closed. What is the way to do that in JavaFX?
Edit:
I understand that I can override setOnCloseRequest() to perform some operation on window close. The question is what operation should be performed to terminate the entire application?
stage.setOnCloseRequest(new EventHandler<WindowEvent>() {
#Override
public void handle(WindowEvent event) {
stop();
}
});
The stop() method defined in Application class does nothing.
The application automatically stops when the last Stage is closed. At this moment, the stop() method of your Application class is called, so you don't need an equivalent to setDefaultCloseOperation()
If you want to stop the application before that, you can call Platform.exit(), for example in your onCloseRequest call.
You can have all these information on the javadoc page of Application : http://docs.oracle.com/javafx/2/api/javafx/application/Application.html
Some of the provided answers did not work for me (javaw.exe still running after closing the window) or, eclipse showed an exception after the application was closed.
On the other hand, this works perfectly:
primaryStage.setOnCloseRequest(new EventHandler<WindowEvent>() {
#Override
public void handle(WindowEvent t) {
Platform.exit();
System.exit(0);
}
});
For reference, here is a minimal implementation using Java 8 :
#Override
public void start(Stage mainStage) throws Exception {
Scene scene = new Scene(new Region());
mainStage.setWidth(640);
mainStage.setHeight(480);
mainStage.setScene(scene);
//this makes all stages close and the app exit when the main stage is closed
mainStage.setOnCloseRequest(e -> Platform.exit());
//add real stuff to the scene...
//open secondary stages... etc...
}
stage.setOnCloseRequest(new EventHandler<WindowEvent>() {
#Override
public void handle(WindowEvent event) {
Platform.exit();
System.exit(0);
}
});
Did you try this..setOnCloseRequest
setOnCloseRequest(EventHandler<WindowEvent> value)
There is one example
Instead of playing around with onCloseRequest handlers or window events, I prefer calling Platform.setImplicitExit(true) the beginning of the application.
According to JavaDocs:
"If this attribute is true, the JavaFX runtime will implicitly
shutdown when the last window is closed; the JavaFX launcher will call
the Application.stop() method and terminate the JavaFX
application thread."
Example:
#Override
void start(Stage primaryStage) {
Platform.setImplicitExit(true)
...
// create stage and scene
}
Using Java 8 this worked for me:
#Override
public void start(Stage stage) {
Scene scene = new Scene(new Region());
stage.setScene(scene);
/* ... OTHER STUFF ... */
stage.setOnCloseRequest(e -> {
Platform.exit();
System.exit(0);
});
}
For me only following is working:
primaryStage.setOnCloseRequest(new EventHandler<WindowEvent>() {
#Override
public void handle(WindowEvent event) {
Platform.exit();
Thread start = new Thread(new Runnable() {
#Override
public void run() {
//TODO Auto-generated method stub
system.exit(0);
}
});
start.start();
}
});
This seemed to work for me:
EventHandler<ActionEvent> quitHandler = quitEvent -> {
System.exit(0);
};
// Set the handler on the Start/Resume button
quit.setOnAction(quitHandler);
Try
System.exit(0);
this should terminate thread main and end the main program
getContentPane.remove(jfxPanel);
try it (:
in action button try this :
stage.close();
exemple:
Stage stage =new Stage();
BorderPane root=new BorderPane();
Scene scene=new Scene();
Button b= new Button("name button");
b.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
stage.close();
}
});
root.getChildren().add(b);
stage.setTitle("");
stage.setScene(scene);
stage.show();
You MUST override the "stop()" method in your Application instance to make it works. If you have overridden even empty "stop()" then the application shuts down gracefully after the last stage is closed (actually the last stage must be the primary stage to make it works completely as in supposed to be).
No any additional Platform.exit or setOnCloseRequest calls are need in such case.

Categories