1

While building my JavaFX desktop application's GUI I came across this amazing button design that I am trying to implement.

Is there any way of implementing this into a JavaFX desktop application?

I apologize for the lengthy background. For the guicy part please skip to the next section.

On my may to conquer this mission I ..

have read:


have searched for:

  1. "Using JavaFX WebView in JavaFX desktop application" - nothing there.
  2. "Integrating HTML elements into JavaFX FXML files" - nothing there.
  3. "Initializing JavaFX FXML elements using JavaScript" - nothing there.


have been through these StackOverflow questions:


After this journey, what I actually know for sure (please correct me if I'm wrong):

  1. I can specify the FXML elements' event handlers using JavaScript.
  2. It is possible to call the JavaScript method from within Java (no idea how though).
  3. Seems like it is not possible to declare an HTML's element in JavaFX's FXML files.
    • Hence, there is no way of applying these CSS classes to my JFXButton.
      • Hence, (1) is worthless as the JS code manipulates the CSS class.


Tobias Reich's button code:

HTML:

<a href="#" data-title="Awesome Button"></a>

CSS:

a {
    position: relative;
    display: inline-block;
    padding: 1.2em 2em;
    text-decoration: none;
    text-align: center;
    cursor: pointer;
    user-select: none;
    color: white;

    &::before {
        content: '';
        position: absolute;
        top: 0;
        left: 0;
        bottom: 0;
        right: 0;
        background: linear-gradient(135deg, #6e8efb, #a777e3);
        border-radius: 4px;
        transition: box-shadow .5s ease, transform .2s ease; 
        will-change: transform;
        box-shadow: 0 2px 5px rgba(0, 0, 0, .2);
        transform:
            translateY(var(--ty, 0))
            rotateX(var(--rx, 0))
            rotateY(var(--ry, 0))
            translateZ(var(--tz, -12px));
    }

    &:hover::before {
        box-shadow: 0 5px 15px rgba(0, 0, 0, .3);
    }

    &::after {
        position: relative;
        display: inline-block;
        content: attr(data-title);
        transition: transform .2s ease; 
        font-weight: bold;
        letter-spacing: .01em;
        will-change: transform;
        transform:
            translateY(var(--ty, 0))
            rotateX(var(--rx, 0))
            rotateY(var(--ry, 0));
    }
}

body {
    display: flex;
    align-items: center;
    justify-content: center;
    height: 100vh;
    transform-style: preserve-3d;
    transform: perspective(800px);
}

JavaScript:

const docStyle = document.documentElement.style
const aElem = document.querySelector('a')
const boundingClientRect = aElem.getBoundingClientRect()

aElem.onmousemove = function(e) {
    const x = e.clientX - boundingClientRect.left
    const y = e.clientY - boundingClientRect.top

    const xc = boundingClientRect.width/2
    const yc = boundingClientRect.height/2

    const dx = x - xc
    const dy = y - yc

    docStyle.setProperty('--rx', `${ dy/-1 }deg`)
    docStyle.setProperty('--ry', `${ dx/10 }deg`)
}

aElem.onmouseleave = function(e) {
    docStyle.setProperty('--ty', '0')
    docStyle.setProperty('--rx', '0')
    docStyle.setProperty('--ry', '0')
}

aElem.onmousedown = function(e) {
    docStyle.setProperty('--tz', '-25px')   
}

document.body.onmouseup = function(e) {
    docStyle.setProperty('--tz', '-12px')
}


What I have so far:

I can handle the various mouse events one by one. Which makes applying the CSS to my JFXButton the problem I am looking for a solution to.
My FXML:

<JFXButton fx:id="testBTN" onAction="handleTestAction(this)" onMouseEntered="mouseEntered(this)" text="TestButton"/>
<fx:script source="JStestBTN.js"/>

JStestBTN:

load("nashorn:mozilla_compat.js");
importClass(java.lang.System);

function handleTestAction(event) {
    docStyle.setProperty('--tz', '-25px') //not tested, might not work.
}

OR

Since it is possible to do something like this: (based on JavaScript script in a FXML)

<Label fx:id="myLabel" />
<fx:script>
    myLabel.text = "This is the text of my label.";
</fx:script>


I thought I could do something like this:

<JFXButton fx:id="testBTN" text="TestButton"/>
<fx:script>
    testBTN.sendToExternalJS; //where it will apply all the "aElem.onmouseSomething"
</fx:script>

/*OR something like:*/
<JFXButton fx:id="testBTN" text="TestButton"/>
<fx:script source="JStestBTN.js" isItPossibleToPassTheJFXButtonHere?"/>

/*OR if neither is possible:*/
//I think my solution would be getting as close as possible to the button's
//design using the available JavaFX & CSS tools. Plus "translating" the 
//functions from JavaScript to Java+JavaFX, using animations, etc..


So to sum up:

  1. Is it possible to apply this kind of CSS to a Button/JFXButton? (workaround?)
  2. Is it possible to "construct" or initialize the button from an external JavaScript file?
  3. If ((1&2)=="no"), could you point me in the right direction for translating the JS code to Java/JavaFX?

Thank you for bearing with me through this long essay.

Julian Broudy
  • 320
  • 3
  • 15
  • It seems like you are going to need to learn how to create custom nodes. You could use JavaFX WebView to run the JavaScript, but I am guessing that is not what you want to do. http://www.drdobbs.com/jvm/javafx-custom-controls/226600252 – SedJ601 May 24 '19 at 14:06
  • @Sedrick so by "Since you need to define a CustomSkin class, your control is skin-able" still does not mean I could apply an already ready CSS, rather I would have to design it from scratch using JavaFX. Right? – Julian Broudy May 24 '19 at 14:21
  • Yea. I am not very knowledgable about custom controls, but I am guessing that you will need to design this from scratch. [`JFoenix`](http://www.jfoenix.com/) stuff is on `GitHub`. You can probably learn a lot from their code. – SedJ601 May 24 '19 at 15:06
  • IMHO you are approaching this from the wrong angle. Rather than trying to re-invent something from a different conceptual framework (HTML/JavaScript), why not just use JavaFX natively the way it was designed? Please check this resource as it will guide you through producing those simple transforms using JavaFX transforms. You can still style the button with CSS, but the tranforms would be handled by JavaFX. https://docs.oracle.com/javase/8/javafx/visual-effects-tutorial/transformations-intro.htm#CHDCEHJJ – Randy Casburn May 24 '19 at 15:06
  • Well yeah, that's what I thought, was just hoping someone would know of a way to simply integrate the code that is already ready. – Julian Broudy May 24 '19 at 15:11
  • 1
    Here is something else to look at. It looks like you can use `Transitions`. Basically, Use current JavaFX buttons and add a Transition to them. https://rterp.wordpress.com/2015/09/01/creating-custom-animated-transitions-with-javafx/ – SedJ601 May 24 '19 at 16:06
  • 1
    This: _to simply integrate the code that is already ready_ -- by the time you conducted all the sited research, wrote the question, considered and responded to these comments - well yeah, you could have written the JavaFX transform code and been done with it. https://softwareengineering.stackexchange.com/questions/87696/is-copy-paste-programming-bad – Randy Casburn May 24 '19 at 16:32

0 Answers0