Javafx drag-drop does not work in the first time - java

I just made a simple Application which includes FlowPane and some VBoxs which has a Button.
The Main class is like this.
public class Main extends Application {
#Override
public void start(Stage stage) {
Gallery a = new Gallery();
a.setMaxWidth(200);
a.setPrefWidth(200);
Scene scene = new Scene(a);
stage.setTitle("Welcome to JavaFX!");
stage.setScene(scene);
stage.sizeToScene();
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
and this Gallery.class is the main back ground class which extends FlowPane.
public class Gallery extends FlowPane{
public Gallery() {
super();
PlotterPanel p1 = new PlotterPanel(this, "B1" );
getChildren().add(p1);
PlotterPanel p2 = new PlotterPanel(this, "B2");
getChildren().add(p2);
PlotterPanel p3 = new PlotterPanel(this, "B3" );
getChildren().add(p3);
PlotterPanel p4 = new PlotterPanel(this, "B4" );
getChildren().add(p4);
PlotterPanel p5 = new PlotterPanel(this, "B5" );
getChildren().add(p5);
PlotterPanel p6 = new PlotterPanel(this, "B6" );
getChildren().add(p6);
}
}
And PlotterPanel is the VBox which has Button and can be drag-drop in the Gallery.
public class PlotterPanel extends VBox{
private static final String TAB_DRAG_KEY = "titledpane";
private ObjectProperty<VBox> draggingTab;
private Gallery mgallery;
private PlotterPanel self;
public PlotterPanel(Gallery gallery, String name) {
super();
mgallery = gallery;
setPrefWidth(100);
setPrefHeight(100);
self = this;
Button btn = new Button(name);
btn.setEffect(new DropShadow());
getChildren().add(btn);
draggingTab = new SimpleObjectProperty<VBox>();
setOnDragOver(new EventHandler<DragEvent>() {
#Override
public void handle(DragEvent event) {
final Dragboard dragboard = event.getDragboard();
if (dragboard.hasString()
&& TAB_DRAG_KEY.equals(dragboard.getString())
&& draggingTab.get() != null) {
event.acceptTransferModes(TransferMode.MOVE);
event.consume();
}
}
});
setOnDragDropped(new EventHandler<DragEvent>() {
public void handle(final DragEvent event) {
Dragboard db = event.getDragboard();
boolean success = false;
if (db.hasString()) {
Pane parent = mgallery;
Object source = event.getGestureSource();
int sourceIndex = parent.getChildren().indexOf(source);
System.out.println(sourceIndex);
int targetIndex = parent.getChildren().indexOf(self);
System.out.println(targetIndex);
List<Node> nodes = new ArrayList<Node>(parent.getChildren());
if (sourceIndex < targetIndex) {
Collections.rotate(
nodes.subList(sourceIndex, targetIndex + 1), -1);
} else {
Collections.rotate(
nodes.subList(targetIndex, sourceIndex + 1), 1);
}
parent.getChildren().clear();
parent.getChildren().addAll(nodes);
success = true;
}
event.setDropCompleted(success);
event.consume();
}
});
setOnDragDetected(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
Dragboard dragboard = self.startDragAndDrop(TransferMode.MOVE);
ClipboardContent clipboardContent = new ClipboardContent();
clipboardContent.putString(TAB_DRAG_KEY);
dragboard.setContent(clipboardContent);
draggingTab.set(self);
event.consume();
}
});
}
}
The problem is that when i drag the PlotterPanel in the Gallery, it can`t be dragged at the first time. And i works after second try.
It shows the dragging box when i start dragging, but when i try to drop on the other Node the Mouse point shows the x sign.
but when the target is already tried Node to be dragged, i can drop on that Node.
How can i make the Drag-drop works well in JavaFX?

The problem is in your condition to accept the drag:
if (dragboard.hasString()
&& TAB_DRAG_KEY.equals(dragboard.getString())
&& draggingTab.get() != null) {
event.acceptTransferModes(TransferMode.MOVE);
event.consume();
}
You are checking the draggingTab of the target, not the source. If the target hasn't been dragged itself, its draggingTab property will still be null. If you have dragged the target already, then it won't be null and it will accept the drag.
Did you mean to make draggingTab static?

Related

javafx reopen minimized window via stage(?) method

SO, I have a JavaFX application with an already implemented Tray that needs 1 option to reopen the window/stage minimized by this GuiController function, which is called by the fxml:
`public void minimizeImageViewClick(MouseEvent mouseEvent) {
if (mouseEvent.getSource() == minimizeImageView) {
stage = (Stage) ((ImageView) mouseEvent.getSource()).getScene().getWindow();
stage.setIconified(true);
}
if(mouseEvent.getSource() == minimizePane){
stage = (Stage) ((Pane) mouseEvent.getSource()).getScene().getWindow();
stage.setIconified(true);
}
}`
There is also one to maximize, implemented by the same means:
public void maximizeImageViewClick(MouseEvent mouseEvent) {
if (mouseEvent.getSource() == maximizeImageView) {
if (ExamAlertStateController.getInstance().getWindowSizeState() == WindowSizeState.INIT) {
stage = (Stage) ((ImageView) mouseEvent.getSource()).getScene().getWindow();
stage.setMaximized(true);
update();
ExamAlertStateController.getInstance().setWindowSizeState(WindowSizeState.MAXIMIZED);
} else {
stage = (Stage) ((ImageView) mouseEvent.getSource()).getScene().getWindow();
stage.setMaximized(false);
update();
ExamAlertStateController.getInstance().setWindowSizeState(WindowSizeState.INIT);
}
}
}`
A piece of the Tray, with the Open (Abrir) option I need to implement and another which only change the screen and the state, as all the other after that:
# SpringBootApplication
public class Application {
//private final MenuItem menuItemSelectedFile;
//Stage stage;
private SystemTray systemTray;
public static final URL MULTI_LOGO = Application.class.getResource("source.png");
private Timer evaluatorTimer;
public static void main(String[] args) {
* code *
}
public Application() {
Log.i(this.getClass().getName(),"Text");
SystemTray.FORCE_GTK2=true;
SystemTray.DEBUG = true;
CacheUtil.clear();
this.systemTray = SystemTray.get();
if (systemTray == null) {
throw new RuntimeException("text!");
}
systemTray.setTooltip("text");
systemTray.setImage(MULTI_LOGO);
systemTray.setStatus("TEXT");
Menu mainMenu = systemTray.getMenu();
MenuItem openMenuItem = new MenuItem("Abrir", new ActionListener() {
#Override
public void actionPerformed(final ActionEvent e) {
}
});
openMenuItem.setTooltip("Abrir programa");
mainMenu.add(openMenuItem);
mainMenu.add(new Separator());
MenuItem loginMenuItem = new MenuItem("Login", new ActionListener() {
#Override
public void actionPerformed(final ActionEvent e) {
ExamAlertStateController.getInstance().setWindowState(WindowState.LOGIN);
}
});
loginMenuItem.setTooltip("Login Text");
mainMenu.add(loginMenuItem);
mainMenu.add(new Separator());
The stage creation in the View file:
public class eaView extends Application {
private static final long ONE_SECOND = 1000;
private static double xOffset = 0;
private static double yOffset = 0;
private boolean ignore;
private Timer updaterTimer;
#Override
public void start(Stage stage) throws Exception {
FXMLLoader loader = new FXMLLoader();
URL urlLoadingScreen = getClass().getResource("/fxml/source.fxml");
loader.setLocation(urlLoadingScreen);
GridPane gridLoadingScreen = loader.load();
Scene scene = new Scene(gridLoadingScreen);
stage.initStyle(StageStyle.UTILITY);
stage.setOpacity(0);
stage.setHeight(0);
stage.setWidth(0);
stage.show();
Stage mainStage = new Stage();
//stage.setResizable(false);
//mainStage.setResizable(false);
mainStage.initOwner(stage);
mainStage.initStyle(StageStyle.UNDECORATED);
mainStage.setScene(scene);
mainStage.show();
So, I wasn't able to to call the maximizeImageViewClick function to it - I can by making it static, but it calls an update() method which contains a lot of FXML objects which cannot be altered, couldn't found the proper stage way of doing it (the attempts:
stage.setScene(scene);
stage.setMaxHeight(0);
stage.setMaxWidth(0);
stage.setOpacity(0);
stage.setIconified(true);
//ExamAlertView.
System.out.println("foi");
//ExamAlertView.
//System.out.println(stage.getProperties());
stage.show();
//if (ExamAlertStateController.getInstance().getWindowSizeState() == WindowSizeState.INIT) {
//stage = (Stage) ((ImageView) e.getSource()).getScene().getWindow();
//stage.setIconified(false);
//stage.setMaximized(true);
//stage.show();
//ImageView
//ExamAlertGuiController.setMinimizeImageView(ExamAlertGuiController.maximizeImageView);
System.out.println("foi2");
//ExamAlertGuiController.update();
ExamAlertStateController.getInstance().setWindowSizeState(WindowSizeState.MAXIMIZED);
/* } else {
stage = (Stage) ((ImageView) e.getSource()).getScene().getWindow();
stage.setMaximized(false);
stage.setIconified(false);
//ExamAlertGuiController.update();
ExamAlertStateController.getInstance().setWindowSizeState(WindowSizeState.INIT);
}*/
//System.out.println(stage.isIconified());
) which was only possible by making
public static Stage stage;
public static Scene scene;
in the GuiController file.
Really out of ideas here. Already did read the javafx.stage class the best I could.
Maybe I'm trying to access the wrong stage - stage UTILITY to remove taskbar button, mainStage UNDECORATED is the real deal, yet can't reach it - but I dont know....
How do I do this?
Thanks in advance.

How to drag and drop button onto GridPane?

I'm working on a school project creating a simple battleship game and i want to use the Drag And Drop function to drag buttons from HBox on the bottom of the screen to the GridPane that the player uses to place ships on. But i can't get it to work properly. Here's a picture of my board per now.
I have tried to use the button.setOnMouseDragged(e -> {CODE HERE}); but it doesnt work.
Here is the code i used for my window
public class GridOrganizer {
private BorderPane borderPane;
public GridOrganizer() {
borderPane = new BorderPane();
borderPane.setStyle("-fx-background-color: grey;");
borderPane.setPrefHeight(600);
borderPane.setPrefWidth(600);
createGrid();
}
public void createGrid() {
//Creates the grids where the game is played and buttons/ships to place on grid
GridPane playerGrid = new GridPane();
GridPane enemyGrid = new GridPane();
Insets padding = new Insets(10);
//Create playergrid
for (int i = 0; i < 10; i++) {
playerGrid.getColumnConstraints().add(new ColumnConstraints(50)); //50 wide
playerGrid.getRowConstraints().add(new RowConstraints(50));
}
//Create enemygrid
for (int i = 0; i < 10; i++) {
enemyGrid.getColumnConstraints().add(new ColumnConstraints(50)); //50 wide
enemyGrid.getRowConstraints().add(new RowConstraints(50));
}
//looping through row and columns and adds buttons
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
Button button = new Button();
button.setPrefHeight(50);
button.setPrefWidth(50);
GridPane.setConstraints(button, j, i); //(button, column, row)
playerGrid.getChildren().add(button); //add button on each index
button.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent arg0) {
//HIT or MISS
System.out.println("Row: " + GridPane.getRowIndex(button) + ", Column: " + GridPane.getColumnIndex(button));
button.setStyle("-fx-background-color: grey;");
}
});
}
}
//..same with enemy grid
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
Button button = new Button();
button.setPrefHeight(50);
button.setPrefWidth(50);
GridPane.setConstraints(button, j, i); //(button, column, row)
enemyGrid.getChildren().add(button); //add button on each index
button.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent arg0) {
System.out.println("Row: " + GridPane.getRowIndex(button) + ", Column: " + GridPane.getColumnIndex(button));
button.setStyle("-fx-background-color: grey;");
}
});
}
}
//Make buttons for the ships
Button rowboat = new Button("Rowboat");
Button sailboat = new Button("Sailboat");
Button submarine = new Button("Submarine");
Button destroyer = new Button("Destroyer");
Button battleship = new Button("Battleship");
//Size the ship buttons to match game description
battleship.setPrefHeight(50);
battleship.setPrefWidth(250); //size 5
destroyer.setPrefHeight(50);
destroyer.setPrefWidth(200); //size 4
submarine.setPrefHeight(50);
submarine.setPrefWidth(150); //size 3
sailboat.setPrefHeight(50);
sailboat.setPrefWidth(150); //size 3
rowboat.setPrefHeight(50);
rowboat.setPrefWidth(100); //size 2
//Drags button
rowboat.setOnMouseDragged(e -> {
//CODE HERE
});
//Drops button on grid
//CODE HERE
sailboat.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent arg0) {
//PLACE SHIP
}
});
submarine.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent arg0) {
//PLACE SHIP
}
});
destroyer.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent arg0) {
//PLACE SHIP
}
});
battleship.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent arg0) {
//PLACE SHIP
}
});
HBox ships = new HBox(); //Horizontal box
ships.getChildren().addAll(rowboat, sailboat, submarine, destroyer, battleship); //Add buttons to horizontal box
//Add grids and ship buttons to pane with padding
borderPane.setLeft(enemyGrid);
BorderPane.setMargin(enemyGrid, padding);
borderPane.setRight(playerGrid);
BorderPane.setMargin(playerGrid, padding);
borderPane.setBottom(ships);
BorderPane.setMargin(ships, padding);
}
public Pane getGrid() {
return borderPane;
}
}
The plan here is to start a drag event with the data needed to create your button when the drag event finished. In your code, it looks like you have added the Buttons into the Grid already. That means you need to only transfer a String to change the Button's text. In my code, I am using a StackPane when creating the Grid. I then create and add the Buttons later. You approach may be better. I have looked that far. I have added an MCVE (Altered code from here):
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.input.*;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
/**
* Demonstrates a drag-and-drop feature.
*/
public class HelloDragAndDrop extends Application
{
#Override
public void start(Stage stage)
{
//Source Buttons.
final Button boat1 = new Button("boat1");
final Button boat2 = new Button("boat2");
final Button boat3 = new Button("boat3");
final Button boat4 = new Button("boat4");
//Adding OnDragDetected to source Buttons.
setOnDragDetected(boat1);
setOnDragDetected(boat2);
setOnDragDetected(boat3);
setOnDragDetected(boat4);
//Adding onDragDone to source Buttons.
setOnDragDone(boat1);
setOnDragDone(boat2);
setOnDragDone(boat3);
setOnDragDone(boat4);
//Creating GridPane
GridPane gridPane = new GridPane();
gridPane.setVgap(5);
gridPane.setHgap(5);
gridPane.setPadding(new Insets(5, 5, 5, 5));
gridPane.setStyle("-fx-background-color: black;");
//Adding StackPane to every Cell in the GridPane and Adding the Target Events to each StackPane.
for (int i = 0; i < 6; i++) {
StackPane stackPane = new StackPane();
stackPane.setPrefSize(150, 50);
stackPane.setStyle("-fx-background-color: yellow;");
setOnDragOver(stackPane);
setOnDragEntered(stackPane);
setOnDragExited(stackPane);
setOnDragDropped(stackPane);
gridPane.add(stackPane, i / 3, i % 3);
}
HBox root = new HBox(new VBox(boat1, boat2, boat3, boat4), gridPane);
stage.setTitle("Hello Drag And Drop");
Scene scene = new Scene(root, 400, 200);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args)
{
Application.launch(args);
}
//source events handlers
public void setOnDragDetected(Button source)
{
source.setOnDragDetected((MouseEvent event) -> {
/* drag was detected, start drag-and-drop gesture*/
System.out.println("onDragDetected");
/* allow any transfer mode */
Dragboard db = source.startDragAndDrop(TransferMode.ANY);
/* put a string on dragboard */
ClipboardContent content = new ClipboardContent();
content.putString(source.getText());
db.setContent(content);
event.consume();
});
}
public void setOnDragDone(Button source)
{
source.setOnDragDone((DragEvent event) -> {
/* the drag-and-drop gesture ended */
System.out.println("onDragDone");
/* if the data was successfully moved, clear it */
// if (event.getTransferMode() == TransferMode.MOVE) {
// source.setText("");
// }
event.consume();
});
}
//target event handlers
public void setOnDragOver(StackPane target)
{
target.setOnDragOver((DragEvent event) -> {
/* data is dragged over the target */
System.out.println("onDragOver");
/* accept it only if it is not dragged from the same node
* and if it has a string data */
if (event.getGestureSource() != target
&& event.getDragboard().hasString()) {
/* allow for both copying and moving, whatever user chooses */
event.acceptTransferModes(TransferMode.COPY_OR_MOVE);
}
event.consume();
});
}
public void setOnDragEntered(StackPane target)
{
target.setOnDragEntered((DragEvent event) -> {
/* the drag-and-drop gesture entered the target */
System.out.println("onDragEntered");
/* show to the user that it is an actual gesture target */
if (event.getGestureSource() != target
&& event.getDragboard().hasString()) {
target.setStyle("-fx-background-color: green;");
}
event.consume();
});
}
public void setOnDragExited(StackPane target)
{
target.setOnDragExited((DragEvent event) -> {
/* mouse moved away, remove the graphical cues */
target.setStyle("-fx-background-color: transparent;");
event.consume();
});
}
public void setOnDragDropped(StackPane target)
{
target.setOnDragDropped((DragEvent event) -> {
/* data dropped */
System.out.println("onDragDropped");
/* if there is a string data on dragboard, read it and use it */
Dragboard db = event.getDragboard();
boolean success = false;
if (db.hasString()) {
//target.setText(db.getString());
Button tempBoat = new Button(db.getString());
tempBoat.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
target.getChildren().clear();
target.getChildren().add(tempBoat);
success = true;
}
/* let the source know whether the string was successfully
* transferred and used */
event.setDropCompleted(success);
event.consume();
});
}
}
In this code, the Buttons that represent the Boats all have onDragDetected and onDragDone event handlers attached. They are considered Source/start of a Drag event. For every cell in the GridPane, a StackPane is added. These StackPanes are considered the Target/areas to drop drag events. Each StackPane has onDragOver, onDragEntered, onDragDropped, and onDragExited attached. Once a drag event is complete, the StackPane/Target that receives the event gets a new Button as a child with the same name as the Source Button.

JavaFX: Disable all components while a process is running and show progress indicator

I have a method that read values from the the database and returns a Map<Integer,String>. This method takes some time to return the map.
Till the time values are getting read I want a progress indicator(only loading ring like indicator will be enough,no need for progress bar) to be displayed on screen and all other components should be disabled till the time progress bar is shown.
public void scanDevice() {
ObservableList<TextField> list = FXCollections.observableArrayList(vehicleId, vehicleName, deviceType,
offboardBroker1, offboardBroker2, postfixQueue, pKIServer);
editedValuesMap.clear();
// devicePlugged = true;
if (cbChooseProject.getSelectionModel().getSelectedItem() != null) {
try {
devicePlugged = dsAdapter.getAdapter();
if (devicePlugged) {
if (bScanDevice.isFocused()) {
readMap = new HashMap<Integer, String>();
//Process Start
readMap = dsAdapter.initScan();
//Process End
if (!readMap.isEmpty() && readMap != null) {
isWritten = true;
isDeviceSideEnabled();
editDeviceContents.setDisable(false);
vehicleId.setText(readMap.get(0));
vehicleName.setText(readMap.get(1));
deviceType.setText(readMap.get(2));
offboardBroker1.setText(readMap.get(3));
offboardBroker2.setText(readMap.get(4));
postfixQueue.setText(readMap.get(5));
pKIServer.setText(readMap.get(6));
lContentsSerialNo.setText(readMap.get(7));
}
}
}
You could disabled all nodes with a method like the following but if you are also wanting to wait while something is happening an overlay using StackPanes may be the preferred choice.
public void setNodesDiabled(boolean disable, Node... nodes) {
for(Node node : nodes) {
node.setDisable(disable);
}
}
With an arbitrary node count, you can disable and re-enable as many nodes that are relevant to the process. It also helps to clean up as you won't have several node.setDisable(true); node2.setDisable(true); and so on.
Here in this example you won't need setNodesDisabled() because the StackPane overlay prevents clicking anything other than what's inside it. The background color is gray with 70% alpha so that you can tell it's an overlay.
public class ProgressExample extends Application {
public StackPane layout, main, progress;
public StackPane createProgressPane() {
ProgressIndicator indicator = new ProgressIndicator();
indicator.setMaxHeight(50);
indicator.setMaxWidth(50);
StackPane pane = new StackPane();
pane.setAlignment(Pos.CENTER);
pane.setStyle("-fx-background-color: rgba(160,160,160,0.7)");
pane.getChildren().add(indicator);
Task<Void> task = new Task<Void>(){
protected Void call() throws Exception {
// Your process here.
// Any changes to UI components must be inside Platform.runLater() or else it will hang.
Thread.sleep(2000);
Platform.runLater(() -> {
layout.getChildren().remove(pane);
});
return null;
}
};
new Thread(task).start();
return pane;
}
public StackPane createMainPane() {
Label label = new Label("Hello World!");
label.setFont(Font.font("Tahoma", FontWeight.SEMI_BOLD, 16));
Button start = new Button("Start Process");
start.setOnAction(action -> {
progress = createProgressPane();
layout.getChildren().add(progress);
});
VBox vbox = new VBox(10);
vbox.setAlignment(Pos.CENTER);
vbox.getChildren().addAll(label, start);
vbox.setPadding(new Insets(10,10,10,10));
StackPane pane = new StackPane();
pane.getChildren().add(vbox);
return pane;
}
public void start(Stage stage) throws Exception {
main = createMainPane();
layout = new StackPane();
layout.getChildren().add(main);
Scene scene = new Scene(layout, 900, 550);
stage.setScene(scene);
stage.setTitle("Progress Example");
stage.setOnCloseRequest(e -> {
Platform.exit();
System.exit(0);
});
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
I believe the problem is that you are trying to change the values of TextFields inside the Task which is not the FX application thread which is why you are getting Not on FX application thread. To fix this you need to put your lines that modify nodes inside a Platform.runLater() like the following to your if statement.
if (readMap != null && !readMap.isEmpty()) { // Swap the order, can't check empty if it's null.
isWritten = true;
isDeviceSideEnabled();
Platform.runLater(() -> {
editDeviceContents.setDisable(false);
vehicleId.setText(readMap.get(0));
vehicleName.setText(readMap.get(1));
deviceType.setText(readMap.get(2));
offboardBroker1.setText(readMap.get(3));
offboardBroker2.setText(readMap.get(4));
postfixQueue.setText(readMap.get(5));
pKIServer.setText(readMap.get(6));
lContentsSerialNo.setText(readMap.get(7));
});
}
Here is an SSCCE:
It uses a Service that can be started more than once. It is not completebut something to start with.
public class Main extends Application {
#Override
public void start(Stage primaryStage) {
BorderPane root = new BorderPane();
Scene scene = new Scene(root, 400, 400);
scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
Service<Void> serv = new Service<Void>() {
#Override
protected Task<Void> createTask() {
return new Task<Void>() {
#Override
protected Void call() throws Exception {
int maxWork = 10;
for (int i = 0; i < maxWork; i++) {
Thread.sleep(1000);
updateProgress(i + 1, maxWork);
}
return null;
}
#Override
protected void succeeded() {
super.succeeded();
updateProgress(1, 1);
}
#Override
protected void cancelled() {
super.cancelled();
updateProgress(1, 1);
}
#Override
protected void failed() {
super.failed();
updateProgress(1, 1);
}
};
}
};
ProgressIndicator pi = new ProgressIndicator();
pi.progressProperty().bind(serv.progressProperty());
Button bStart = new Button("Start");
bStart.setOnAction(e -> {
serv.reset();
serv.start();
});
root.setCenter(bStart);
root.setBottom(pi);
primaryStage.setScene(scene);
primaryStage.show();
pi.getScene().getRoot().disableProperty().bind(serv.runningProperty());
}
public static void main(String[] args) {
launch(args);
}
}
In CSS I added:
.progress-indicator:disabled {
-fx-opacity: 1;
}

Delay in displaying the node in JavaFx running Android

I have a Dialog class with a wait method in it to display my custom Progress Dialog:
public static void wait(String title){
isOpen = true;
ProgressIndicator progress = new ProgressIndicator(-1);
Label label = new Label(title);
label.getStyleClass().add("login-label");
HBox container = new HBox();
container.setStyle("-fx-background-color: white;");
container.setAlignment(Pos.CENTER);
container.getChildren().addAll(progress,label);
if(Main.HEIGHT < 700){
container.setSpacing(10);
container.setPadding(new Insets(10,15,10,15));
}else if(Main.HEIGHT < 1200){
container.setSpacing(15);
container.setPadding(new Insets(15,20,15,20));
}else{
container.setSpacing(20);
container.setPadding(new Insets(20,30,20,30));
}
show("", container);
}
I have this piece of code in one of my class to dislay my Progess Dialog:
Platform.runLater(new Runnable(){
#Override
public void run() {
Dialog.wait("Processing, please wait...");
}
});
But unfortunately there is a delay in its showing, I also tried to wrap it inside a Thread but it didn't work as well, I tried to run it in Desktop and it works perfectly but why not in my Android Device?
Here's the complete code:
download = new Button("Download");
download.getStyleClass().add("terminal-button");
download.setPrefWidth(Main.HEIGHT > 700 ? 180 : 140);
download.setOnAction(new EventHandler<ActionEvent>(){
#Override
public void handle(ActionEvent event) {
Platform.runLater(new Runnable(){
#Override
public void run() {
Dialog.wait("Processing, please wait...");
}
});
Platform.runLater(new Runnable(){
#Override
public void run() {
//GET THE SELECTED AREAS FOR DOWNLOAD
List<String> selectedSectors = new ArrayList();
String sectorid = null;
for(Sector r : listView.getItems()){
if(r.isSelected()){
selectedSectors.add(r.getObjid());
sectorid = r.getObjid();
}
}
if(selectedSectors.size() > 1){
Dialog.hide();
Dialog.showAlert("Multiple downloads are not supported!");
return;
}
MobileDownloadService mobileSvc = new MobileDownloadService();
//INIT DOWNLOAD
Map params = new HashMap();
params.put("assigneeid", SystemPlatformFactory.getPlatform().getSystem().getUserID());
params.put("sectorid", sectorid);
batchid = mobileSvc.initForDownload(params);
int recordcount = -1;
while (true) {
int stat = mobileSvc.getBatchStatus(batchid);
if ( stat < 0 ) {
try {
Thread.sleep(2000);
}catch(Throwable t){;}
} else {
recordcount = stat;
break;
}
}
if ( recordcount <= 0 ) {
Dialog.hide();
Dialog.showError("No data to download");
return;
}
downloadsize = recordcount;
accountList = new ArrayList();
int start=0, limit=50;
while ( start < recordcount ) {
params = new HashMap();
params.put("batchid", batchid);
params.put("_start", start);
params.put("_limit", limit);
List<Map> list = mobileSvc.download(params);
//if ( list != null ) accountList.addAll( list );
System.out.println("fetch results is " + list.size());
//new Thread( new ProcessDownloadResultTask(start,list)).start();
start += limit;
}
Dialog.hide();
//SAVE AREA, STUBOUTS
clearSector();
for(Sector r : listView.getItems()){
if(r.isSelected()){
saveSector(r);
}
}
label.setVisible(true);
progressbar.setVisible(true);
progressbar.progressProperty().bind(task.progressProperty());
new Thread(task).start();
download.setText("Cancel");
download.setDisable(false);
download.setOnAction(new EventHandler<ActionEvent>(){
#Override
public void handle(ActionEvent event) {
continueDownload = false;
label.setVisible(false);
progressbar.setVisible(false);
download.setText("Back");
download.setOnAction(new EventHandler<ActionEvent>(){
#Override
public void handle(ActionEvent event) {
Main.ROOT.setCenter(new Home().getLayout());
}
});
root.setOnKeyReleased(new EventHandler<KeyEvent>(){
#Override
public void handle(KeyEvent event) {
if(event.getCode() == KeyCode.ESCAPE){
if(Dialog.isOpen){ Dialog.hide(); return; }
Main.ROOT.setCenter(new Home().getLayout());
}
}
});
Map params = new HashMap();
params.put("batchid", batchid);
params.put("downloadedlist", downloadedList);
MobileDownloadService svc = new MobileDownloadService();
svc.cancelDownload(params);
}
});
download.setDisable(false);
}
});
}
});
The said scenario occur when you click the button, the output should be: Dialog will popup IMMEDIATELY as soon as you click the button, but sad to say, the Dialog will display after the entire process of the button was completed! I tried to wrap it in Thread but no luck!
Please help me! Any idea?
This is a short sample showing how can you use a Gluon's Dialog to handle the progress notification of a background task.
It uses a dummy task, but you can see how to handle showing and hiding the dialog, as well as using a ProgressBar to notify the progress, and even cancelling the task.
Using the Gluon Plugin for your IDE, create a Single View mobile project, and modify the view with this one:
public class BasicView extends View {
public BasicView(String name) {
super(name);
Dialog dialog = new Dialog("Download Progress");
final ProgressBar progressBar = new ProgressBar();
progressBar.setPrefWidth(200);
final Label label = new Label("Process has ended");
VBox vbox = new VBox(10, new Label("Download in progress..."), progressBar, label);
vbox.setAlignment(Pos.CENTER);
dialog.setContent(vbox);
final Button cancel = new Button("Cancel");
dialog.getButtons().add(cancel);
dialog.setOnShown(e -> {
cancel.setDisable(false);
label.setVisible(false);
final Task<Void> task = createDownloadTask();
progressBar.progressProperty().bind(task.progressProperty());
cancel.setOnAction(a -> task.cancel(true));
task.setOnCancelled(c -> {
PauseTransition pause = new PauseTransition(Duration.seconds(1));
pause.setOnFinished(t -> dialog.hide());
cancel.setDisable(true);
label.setVisible(true);
pause.play();
});
task.setOnSucceeded(s -> {
PauseTransition pause = new PauseTransition(Duration.seconds(1));
pause.setOnFinished(t -> dialog.hide());
cancel.setDisable(true);
label.setVisible(true);
pause.play();
});
final Thread thread = new Thread(task);
thread.setDaemon(true);
thread.start();
});
Button button = new Button("Download");
button.setGraphic(new Icon(MaterialDesignIcon.CLOUD_DOWNLOAD));
button.setOnAction(e -> dialog.showAndWait());
setCenter(new StackPane(button));
}
#Override
protected void updateAppBar(AppBar appBar) {
appBar.setNavIcon(MaterialDesignIcon.MENU.button(e -> System.out.println("Menu")));
appBar.setTitleText("Downloads View");
}
private Task<Void> createDownloadTask() {
return new Task<Void>() {
#Override
protected Void call() throws Exception {
for(int i = 0; i <= 10; i++) {
if (isCancelled()) {
break;
}
try {
Thread.sleep(1000);
updateProgress(i, 10);
} catch (InterruptedException ie) {
if (isCancelled()) {
break;
}
}
}
return null;
}
};
}
}
Try replacing the dummy task with yours and see how it goes.
I solved the problem by separating its execution in one of the mouse events, instead of putting all together in the setOnAction, I placed the code Dialog.wait("Processing, please wait..."); in the setOnMousePressed, like this:
download.setOnMousePressed(new EventHandler<MouseEvent>(){
#Override
public void handle(MouseEvent event) {
if(!Dialog.isOpen) Dialog.wait("Processing, please wait...");
}
});
download.setOnMouseReleased(new EventHandler<MouseEvent>(){
#Override
public void handle(MouseEvent event) {
doDownload();
}
});
This code works!

Set new button dragdetected problema

I use JavaFX, project has 2 Anchorpane (pane and paneDrop) , one of them has a button, when I drag this button create new button , when dragdropped setOnDragDetected method to new button. Problem is, when I try drag one of new butoons only last creating button move.
#FXML
private Button source;
#FXML
private AnchorPane pane;
#FXML
private AnchorPane paneDrop;
private Button b;
int i = 1;
int moveI = 0;
#FXML
private void dragDetected(MouseEvent event) {
System.out.println("onDragDetected");
b = new Button(i + "");
i++;
pane.getChildren().add(b);
b.setLayoutX(source.getLayoutX());
b.setLayoutY(source.getLayoutX());
/* drag was detected, start drag-and-drop gesture*/
paneDrop.setOnDragOver(new EventHandler<DragEvent>() {
#Override
public void handle(DragEvent k) {
paneDrop.setOnDragDropped(new EventHandler<DragEvent>() {
#Override
public void handle(DragEvent k1) {
System.out.println("ondragExited");
pane.getChildren().remove(b);
paneDrop.getChildren().add(b);
b.setLayoutX(k1.getSceneX() - paneDrop.getLayoutX());
b.setLayoutY(k1.getSceneY() - paneDrop.getLayoutY());
b.setOnDragDetected(new EventHandler<MouseEvent>() {
public void handle(MouseEvent t) {
/* drag was detected, start a drag-and-drop gesture*/
/* allow any transfer mode */
paneDrop.setOnDragOver(new EventHandler<DragEvent>() {
#Override
public void handle(DragEvent t) {
System.out.println("ondragOver");
paneDrop.setOnDragDropped(new EventHandler<DragEvent>() {
#Override
public void handle(DragEvent t1) {
System.out.println("ondragOver");
if (t1.getGestureSource() != pane
&& t1.getDragboard().hasString()) {
t1.acceptTransferModes(TransferMode.COPY_OR_MOVE);
}
t1.consume();
}
});
b.setLayoutX(t.getSceneX());
b.setLayoutY(t.getSceneY() - 224);
if (t.getGestureSource() != pane
&& t.getDragboard().hasString()) {
t.acceptTransferModes(TransferMode.COPY_OR_MOVE);
}
t.consume();
}
});
Dragboard db = b.startDragAndDrop(TransferMode.MOVE);
System.out.println("ttttttttttttt");
/* Put a string on a dragboard */
ClipboardContent content = new ClipboardContent();
content.putString(b.getText());
db.setContent(content);
t.consume();
}
});
k1.consume();
}
});
System.out.println("ondragOver");
b.setLayoutX(k.getSceneX() - pane.getLayoutX());
b.setLayoutY(k.getSceneY() - pane.getLayoutY());
if (k.getGestureSource() != pane
&& k.getDragboard().hasString()) {
k.acceptTransferModes(TransferMode.COPY_OR_MOVE);
}
k.consume();
}
});
/* allow any transfer mode */
Dragboard db = source.startDragAndDrop(TransferMode.MOVE);
/* put a string on dragboard */
ClipboardContent content = new ClipboardContent();
//System.out.println(source.getText());
content.putString(source.getText());
db.setContent(content);
event.consume();
}

Categories