Leap Motion & JavaFX – Radial Menu – DrawKidFX

Today I’d like to share with you my last try on radial menu. I decided to inspire from the Win 8 radial menu to create a color chooser menu, very simple for now. Here is the original video

http://www.youtube.com/watch?v=UUe56Hb5Z_w

It did not take long to create the simple color chooser menu. I wanted to use it with my new X-mas gift that is a LeapMotion. So I decided to create a drawing program for my kids. Here is the result for now :

The gesture part is the following :

  • One finger pointed and the position along z axis is negative -> drawing 
  • One finger pointed and the position along z axis is positive -> moving cursor
  • One finger pointed and the position along z axis transitioned from positive to negative value -> new drawing line
  • One hand opened (at least 4 fingers) the color chooser menu is displayed
  • One hand opened the hand position is used to move the cursor (and choose a color by going through one)

Some lesson learned when integrating the leap motion with Java(FX) :

  • Do not rely on the LeapMotion threading model. It creates a NEW Thread to notify each frame and it did crash my JVM very often… I hope LeapMotion guys will offer update that change this performance problem
  • Instead, Poll it at the rate you desire, using for example the ExecutorServices API and the created controller API. No crash anymore…
  • Take care to perform the JavaFX update into the JavaFX Thread using Platform.runLater()
  • You can use the AWT Robot to move the mouse
  • Checking the gesture stability is not that easy. I hope LeapMotion guys will offer us update that includes new gesture support !

Code available very soon on github https://github.com/MrLoNee ! in project LeapDrawKidFX.

LoNee

6 comments

  1. Hi again,
    Thx again for the code stuff !!
    Like I asked last time, could yu just do something to show the slide of a pane in a stage.
    Yes I know I am asking a bit too much but all I’m saying is that I just need some tips and a little something to help, I’m only asking this to my end term project, I just need this ^^

  2. here I tried some stuff alone

    AnimationClass.java

    /**
    * Created by Minedun6 on 02/01/14.
    */

    import javafx.animation.Interpolator;
    import javafx.animation.ParallelTransition;
    import javafx.animation.TranslateTransition;
    import javafx.application.Application;
    import javafx.event.ActionEvent;
    import javafx.event.EventHandler;
    import javafx.scene.layout.Pane;
    import javafx.scene.layout.StackPane;
    import javafx.scene.shape.Rectangle;
    import javafx.stage.Stage;
    import javafx.util.Duration;

    public class AnimationClass extends StackPane{

    private Pane actualPane;
    private Pane animatePane;

    private int currentPane =1;

    private ParallelTransition slideTransition = new ParallelTransition();

    private final static double SLIDE_ANIMATION_DURATION = 0.7;

    public AnimationClass(final Pane actualPane, final Pane animatePane){
    this.actualPane = actualPane;
    this.animatePane = animatePane;

    animatePane.setVisible(false);

    getChildren().addAll(actualPane,animatePane);
    }

    public void SlideToRight(int direction){
    if (slideTransition != null) {
    slideTransition.stop();
    }

    TranslateTransition transition1 = new TranslateTransition(Duration.seconds(SLIDE_ANIMATION_DURATION), animatePane);
    TranslateTransition transition2 = new TranslateTransition(Duration.seconds(SLIDE_ANIMATION_DURATION), actualPane);

    // Set the animatePane to visible.
    animatePane.setVisible(true);

    // Set the clip, so that the translate transition stays within the clip.
    // Use the bounds from one pane.
    setClip(new Rectangle(animatePane.getBoundsInLocal().getWidth(), animatePane.getBoundsInLocal().getHeight()));

    // Move the old pane away from 0. (I added 1px, so that both panes overlap, which makes it look a little smoother).
    transition1.setFromX(-direction * 1);
    // and either to right or to left.
    transition1.setToX(getLayoutBounds().getWidth() * direction + -direction * 1);

    // Move new pane from left or right
    transition2.setFromX(-getBoundsInParent().getWidth() * direction);

    // Move the new pane to 0
    transition2.setToX(0);

    slideTransition = new ParallelTransition();
    slideTransition.getChildren().addAll(transition1, transition2);
    slideTransition.setInterpolator(Interpolator.EASE_OUT);

    slideTransition.play();
    slideTransition.setOnFinished(new EventHandler() {
    @Override
    public void handle(ActionEvent actionEvent) {
    // When we are finished, set the animate pane to invisible and remove the clip.
    animatePane.setVisible(false);
    // If the calendar gets resized, we don’t have any clip.
    setClip(null);
    }
    });

    }

    }

    Main.java

    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.scene.layout.Pane;
    import javafx.stage.Stage;

    /**
    * Created by Minedun6 on 02/01/14.
    */
    public class Main extends Application{
    @Override
    public void start(Stage stage) throws Exception {
    BorderPane pane1 = new BorderPane();
    Button btn1 = new Button(“Slide to Pane2″);
    Label lab = new Label(“Fuck Yeah !!!!!!”);
    pane1.setCenter(btn1);
    pane1.setLeft(lab);
    Pane pane2 = new Pane();
    Button btn2 = new Button(“Slide to Pane1″);
    pane2.getChildren().add(btn2);
    final AnimationClass stackPane = new AnimationClass(pane1, pane2);
    Scene scene = new Scene(stackPane, 400, 400);
    stage.setScene(scene);
    stage.show();
    btn1.setOnAction(new EventHandler() {
    @Override
    public void handle(ActionEvent actionEvent) {
    stackPane.SlideToRight(1);
    }
    });
    btn2.setOnAction(new EventHandler() {
    @Override
    public void handle(ActionEvent actionEvent) {
    stackPane.SlideToRight(-1);
    }
    });
    }

    public static void main(String[] args){
    launch(args);
    }

    }

    but the behaviour of the pane is a bit odd, I would like a little help if not too much asked ^^

    1. I’ve taken a shot at your code. What do you mean by the code is a bit odd ? It seems to me it almost work ? At least I can see the panel sliding :)

  3. Hi, it’s me again,
    This time, I am trying to create an AutoCompletition feature for my ComboBox.
    First here the ideas I’m trying to create:
    instead of what I’ve seen fro the example at : blog.ngopal.com.np
    He’s creating a TextField and a ListView and appending each other… why not use the default ComboBox and show the listview/contextmenu only if the user start typing and then check if the user’s input is inside the ObservableList of the combobox(weither it’s comming from a database or from static content).
    My only concern is the Interface I’ll be implementing, can yu tell me how to do so !!
    I’m not asking for the whole stuff, just the listener/KeyEvents and ….
    Thx again for last time ^^
    And yes, for the sliding effect , I’ve triedusing boolean stuff (when played = false, play slide in an orientation, played = true, and if played = true, play slide in other orientation)

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="" highlight="">