2 Replies Latest reply on Jul 5, 2013 1:25 PM by Andipa

    Drag event handling in JFXPanel has performance implications with expensive event handlers

    Andipa

      We have a drag event handler that is a little expensive, takes something like 20ms. The respective code must be run in a synchronous manner however.

      That is no problem in a pure JavaFX environment, as less drag events are created when CPU load is high.

      However, when embedded into Swing using JFXPanel this adaptation doesn't kick in, lots of drag events are created and the application becomes sluggish.

       

      Is there a way to mimic what JavaFX does in the JFXPanel scenario?

       

      The code below is a self-contained example that demonstrates what I'm describing.

       

      Some results I had:

      -eventHandlerSleep=5 -noswing --> 128 drag events

      -eventHandlerSleep=30 -noswing --> 46 drag events

      -eventHandlerSleep=5  --> 136 drag events

      -eventHandlerSleep=30  --> 135 drag events

       

      {code}import java.util.Arrays;

       

      import javax.swing.*;

       

      import com.sun.glass.ui.Robot;

       

      import javafx.application.Application;

      import javafx.application.Platform;

      import javafx.embed.swing.JFXPanel;

      import javafx.event.EventHandler;

      import javafx.scene.Scene;

      import javafx.scene.input.MouseEvent;

      import javafx.scene.layout.BorderPane;

      import javafx.stage.Stage;

       

      public class DragHandlingTester {

       

          private static long EVENT_HANDLER_SLEEP = 30;

       

          public static void main(String[] args) {

              for (String arg : args) {

                  if (arg.startsWith("-eventHandlerSleep=")) {

                      EVENT_HANDLER_SLEEP = Long.parseLong(arg.split("=")[1]);

                  }

              }

              if (Arrays.asList(args).contains("-noswing")) {

                  Application.launch(JavaFXDragHandlingTestApp.class, args);

              } else {

                  new SwingDragHandlingTestApp();

              }

          }

       

          static class SwingDragHandlingTestApp {

              SwingDragHandlingTestApp() {

                  JFrame frame = new JFrame();

                  final JFXPanel fxMainPanel = new JFXPanel();

                  Platform.runLater(new Runnable() {

                      @Override

                      public void run() {

                          DragTestScene dragTestScene = new DragTestScene();

                          fxMainPanel.setScene(dragTestScene.createScene());

                      }

                  });

                  frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);

                  frame.getContentPane().add(fxMainPanel);

                  frame.setSize(800, 600);

                  frame.setVisible(true);

              }

          }

       

          public static class JavaFXDragHandlingTestApp extends Application {

              @Override

              public void start(Stage primaryStage) {

                  primaryStage.setWidth(800);

                  primaryStage.setHeight(600);

                  primaryStage.setX(0.0);

                  primaryStage.setY(0.0);

                  DragTestScene dragTestScene = new DragTestScene();

                  primaryStage.setScene(dragTestScene.createScene());

                  primaryStage.show();

              }

          }

       

          static class DragTestScene {

       

              private int drags = 0;

       

              public Scene createScene() {

                  new Thread(new Runnable() {

                      @Override

                      public void run() {

                          try {

                              // after 1 second drag mouse across window

                              Thread.sleep(1000);

                              Robot robot = com.sun.glass.ui.Application.GetApplication().createRobot();

                              robot.mouseMove(50, 50);

                              robot.mousePress(1);

                              for (int i = 20; i < 700; i = i + 5) {

                                  robot.mouseMove(i, 50);

                                  Thread.sleep(10);

                              }

                              robot.mouseRelease(1);

                          } catch (Exception e) {

                              e.printStackTrace();

                          }

                      }

                  }).start();

       

                  BorderPane borderPane = new BorderPane();

                  borderPane.setOnMouseDragged(new EventHandler() {

                      @Override

                      public void handle(MouseEvent mouseEvent) {

                          drags++;

                          try {

                              Thread.sleep(EVENT_HANDLER_SLEEP);

                          } catch (InterruptedException ignored) {

                          }

                          System.out.println("Number of drag events: " + drags);

                      }

                  });

                  return new Scene(borderPane);

              }

       

          }

      }

      {code}