SlideShare una empresa de Scribd logo
1 de 130
Descargar para leer sin conexión
Gerrit Grunwald | Developer Advocate | Azul
ABOUT ME...
diabetes
sucks
monitoring


24/7
MONITORING 24/7
DESKTOP APP
The Swift
SWIFT DESKTOP APP
MacOS APP
Show value and history


Last 30 days average


Pattern of last week


Time in range


Settings


Has system tray icon
THE
QUESTION
JAVA FX...?
Can I create that same app in
WINDOWS
Native looking
NATIVE LOOKING WINDOWS
Properties
Title


Buttons for minimize, maximize, close


Resizeable


Draggable


Rounded corners on Macos


Support dark and light themes !


Have toolbuttons, text
fi
elds etc. on Macos !!!
NATIVE LOOKING WINDOWS
Rounded corners
Close, Minimize, Maximize buttons Title
NATIVE LOOKING WINDOWS
Text
fi
eld
Buttons
Greater height
CSS
So let's try to create such a window using
NATIVE LOOKING WINDOWS IN CSS
BorderPane
BorderPane
LAYOUT...
AnchorPane (top)
BorderPane
AnchorPane (top)
LAYOUT...
AnchorPane (top)
HBox
BorderPane
AnchorPane (top)
HBox
LAYOUT...
AnchorPane (top)
BorderPane
AnchorPane (top)
Circle
Circle
Circle
HBox
LAYOUT...
AnchorPane (top)
BorderPane
Region (center)
Region (center)
AnchorPane (top)
Circle
Circle
Circle
HBox
LAYOUT...
Height: 52.5px
Corner radius: 10px rgb(2, 2, 2)
rgb(117, 115, 116)
rgb(133, 131, 132)
rgb(47, 46, 47)
DropShadow
DESIGN HEADER...
tip...
screenshot
Tool
colorpicker
Tool
.header {
-fx-min-height : 52.5;
-fx-max-height : 52.5;
-fx-pref-height : 52.5;
-fx-background-insets: 0, 0.5 0.5 0 0.5, 1 1 0 1, 1.5 1 0 1;
-fx-background-radius: 10 10 0 0, 9.5 9.5 0 0, 9.5 9.5 0 0, 8.5 8.5 0 0;
-fx-background-color : rgb(2, 2, 2),
linear-gradient(to bottom, rgb(117, 115, 115) 0%,
rgb(99, 98, 98) 20%,
rgb(99, 98, 98) 100%),
rgb(133, 131, 132),
rgb(47, 46, 47);
-fx-effect : dropshadow(gaussian, rgba(0, 0, 0, 0.35),
1, 0, 0, 1.5)
}
CSS HEADER...
(Zoomed)
CSS styled AnchorPane .header
public class SimpleHeaderDemo extends Application {




private static final String STYLE = "simple-styles.css";


private AnchorPane header;


@Override public void init() {


header = new AnchorPane();


header.getStyleClass().add("header");


}


@Override public void start(final Stage stage) {


BorderPane pane = new BorderPane();


pane.setPrefSize(600, 200);


pane.setPadding(new Insets(20));


pane.setTop(header);


Scene scene = new Scene(pane);


scene.getStylesheets()


.add(SimpleHeaderDemo.class.getResource(STYLE)


.toExternalForm());


stage.setTitle("Header Demo");


stage.setScene(scene);


stage.show();


stage.centerOnScreen();


}


}


CODE HEADER...
Corner radius: 10px
rgb(2, 2, 2)
rgb(84, 82, 81)
rgb(32, 34, 34)
DESIGN BODY...
.body {
-fx-background-insets: 0, 0 0.5 0.5 0.5, 0 1 1 1;
-fx-background-radius: 0 0 10 10, 0 0 9.5 9.5, 0 0 9.5 9.5;
-fx-background-color : rgb(2, 2, 2),
rgb(84, 82, 81),
rgb(32, 28, 28);
}
CSS BODY...
CSS styled Region .body
(Zoomed)
public class SimpleHeaderDemo extends Application {




private static final String STYLE = "simple-styles.css";


private AnchorPane header;


private Region body;


@Override public void init() {


header = new AnchorPane();


header.getStyleClass().add("header");


body = new Region();


body.getStyleClass().add("body");


}


@Override public void start(final Stage stage) {


BorderPane pane = new BorderPane();


pane.setPrefSize(400, 400);


pane.setPadding(new Insets(20));


pane.setTop(header);


pane.setCenter(body);


Scene scene = new Scene(pane);


scene.getStylesheets()


.add(SimpleHeaderDemo.class.getResource(STYLE)


.toExternalForm());


stage.setTitle("Header Demo");


stage.setScene(scene);


stage.show();


stage.centerOnScreen();


}


}


CODE
.header {
-fx-min-height : 52.5;
-fx-max-height : 52.5;
-fx-pref-height : 52.5;
-fx-background-insets: 0, 0.5 0.5 0 0.5, 1 1 0 1, 1.5 1 0 1;
-fx-background-radius: 10 10 0 0, 9.5 9.5 0 0, 9.5 9.5 0 0, 8.5 8.5 0 0;
-fx-background-color : rgb(2, 2, 2),
rgb(133, 131, 132),
linear-gradient(to bottom, rgb(117, 115, 115) 0%,
rgb(99, 98, 98) 20%,
rgb(99, 98, 98) 100%),
rgb(47, 46, 47);
-fx-effect : dropshadow(gaussian, rgba(0, 0, 0, 0.35),
1, 0, 0, 1.5)
}
.body {
-fx-background-insets: 0, 0 0.5 0.5 0.5, 0 1 1 1;
-fx-background-radius: 0 0 10 10, 0 0 9.5 9.5, 0 0 9.5 9.5;
-fx-background-color : rgb(2, 2, 2),
rgb(84, 82, 81),
rgb(32, 28, 28);
}
CSS
THE RESUL
T
Distance: 8px
Radius: 6px
rgb(236, 107, 95)
rgb(244, 190, 79)
rgb(91, 87, 87) rgb(38, 193, 56)
Distance: 22px
DESIGN BUTTONS...
public class CircleButton extends Circle {




public enum Type {


CLOSE("close"),


MINIMIZE("minimize"),


MAXIMIZE("maximize");


public final String style;


Type(final String style) {


this.style = style;


}


}


public CircleButton(final Type type) {


super(6);


getStyleClass().add(type.style);


}


}


CODE BUTTON...
.close {
-fx-fill : rgb(236, 107, 95); /* RED */
-fx-stroke: derive(rgb(236, 107, 95), -10%);
}
.minimize {
-fx-fill : rgb(244, 190, 79); / * YELLOW */
-fx-stroke: derive(rgb(244, 190, 79), -10%);
}
.maximize {
-fx-fill : rgb(38, 193, 56); /* GREEN */
-fx-stroke: derive(rgb(38, 193, 56), -10%);
}
.close:disabled,
.minimize:disabled,
.maximize:disabled {
-fx-fill : rgb(91, 87, 87); /* GRAY */
-fx-stroke: derive(rgb(91, 87, 87), -10%);
}
CSS BUTTON...
public class SimpleHeaderDemo extends Application {




private static final String STYLE = "simple-styles.css";


private HBox buttonBox;


private AnchorPane header;


private Region body;


@Override public void init() {


CircleButton close = new CircleButton(Type.CLOSE);


CircleButton minimize = new CircleButton(Type.MINIMIZE);


CircleButton maximize = new CircleButton(Type.MAXIMIZE);


buttonBox = new HBox(8, close, minimise, maximize);


buttonBox.setAlignment(Pos.CENTER);


AnchorPane.setTopAnchor(buttonBox, 0d);


AnchorPane.setBottomAnchor(buttonBox, 0d);


AnchorPane.setLeftAnchor(buttonBox, 22d);


header = new AnchorPane(buttonBox);


header.getStyleClass().add("header");


body = new Region();


body.getStyleClass().add("body");


}


@Override public void start(final Stage stage) {...}


}


CODE...
ORIGINAL JAVA FX
ORIGINAL JAVA FX
stage.initStyle(StageStyle.TRANSPARENT)
You need to take care of Resizing + Dragging !!!
SHADOWS


Some tips related to
LAYOUTS...
Dropshadows within
AnchorPane (top)
Region (center)
DropShadow
SHADOWS
"Same" code no shadow...
Left side shows no shadow


Right side shows shadow
why...?
WRONG ORDER...
BorderPane borderPane = new BorderPane();


borderPane.setTop(header);


borderPane.setCenter(content);
AnchorPane anchorPane = new AnchorPane(header, content);


AnchorPane.setTopAnchor(lowerLeftHeader, 0d);


AnchorPane.setRightAnchor(lowerLeftHeader, 0d);


AnchorPane.setLeftAnchor(lowerLeftHeader, 0d);


AnchorPane.setTopAnchor(lowerLeftContent, 50d);


AnchorPane.setRightAnchor(lowerLeftContent, 0d);


AnchorPane.setLeftAnchor(lowerLeftContent, 0d);


2nd
1st
2nd
1st
RIGHT ORDER...
BorderPane borderPane = new BorderPane();


borderPane.setCenter(content);


borderPane.setTop(header);
AnchorPane anchorPane = new AnchorPane(content, header);


AnchorPane.setTopAnchor(lowerLeftHeader, 0d);


AnchorPane.setRightAnchor(lowerLeftHeader, 0d);


AnchorPane.setLeftAnchor(lowerLeftHeader, 0d);


AnchorPane.setTopAnchor(lowerLeftContent, 50d);


AnchorPane.setRightAnchor(lowerLeftContent, 0d);


AnchorPane.setLeftAnchor(lowerLeftContent, 0d);


1st
2nd
1st
2nd
WINDOWS...
Dropshadows for custom
BorderPane


setE
ff
ect(new DropShadow())
DropShadow
Stage
SHADOWS...
Custom windows
Add the shadow the BorderPane


No shadow will show


There is no space to draw the
shadow
SHADOWS...
Custom windows
Add another Region


Keep the Region transparent


Add padding to left, right, bottom


Add the BorderPane to the
Region


Apply the shadow to the
BorderPane
BorderPane


setE
ff
ect(new DropShadow())
DropShadow
Stage
Transparent Region
back to the
buttons...
HOVERED
NORMAL
svg
public class CircleButton extends Circle {




public enum Type {


CLOSE("close"),


MINIMIZE("minimize"),


MAXIMIZE("maximize");


public final String style;


Type(final String style) {


this.style = style;


}


}


public CircleButton(final Type type) {


super(6);


getStyleClass().add(type.style);


}


}
CODE BUTTON...
extends Circle
public class CircleButton extends StackPane {




public enum Type {


CLOSE("close"),


MINIMIZE("minimize"),


MAXIMIZE("maximize");


public final String style;


Type(final String style) {


this.style = style;


}


}


private final Region icon;


public CircleButton(final Type type) {


super();


icon.getStyleClass().add("icon")


getChildren().setAll(icon);


getStyleClass().add(type.style);


}


}
CODE BUTTON...
extends StackPane
Region icon
.close:hover .icon {
-fx-scale-shape : false;
-fx-shape : "M 2,2.5 l 2,0 l 0,2.5 l 2.5,0 l 0,2
l -2.5,0 l 0,2.5 l -2,0 l 0,-2.5
l -2.5,0 l 0,-2 l 2.5,0 l 0,-2.5 z";
}
CSS BUTTON...
adding points to the SVG shape...
.close:hover .icon {
-fx-background-color: rgb(55, 52, 52);
-fx-scale-shape : false;
-fx-shape : "M 2,2.5 l 2,0 l 0,2.5 l 2.5,0 l 0,2
l -2.5,0 l 0,2.5 l -2,0 l 0,-2.5
l -2.5,0 l 0,-2 l 2.5,0 l 0,-2.5 z";
}
CSS BUTTON...
set the
fi
ll color
.close:hover .icon {
-fx-rotate : 45;
-fx-background-color: rgb(55, 52, 52);
-fx-scale-shape : false;
-fx-shape : "M 2,2.5 l 2,0 l 0,2.5 l 2.5,0 l 0,2
l -2.5,0 l 0,2.5 l -2,0 l 0,-2.5
l -2.5,0 l 0,-2 l 2.5,0 l 0,-2.5 z";
}
CSS BUTTON...
rotate the shape by 45°
USE VECTOR DRAWING PROGRAM...
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/
svg11.dtd">
<svg width="12px" height="12px" version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://
www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-
miterlimit:2;">
<path d="M5,2.5l2,0l0,2.5l2.5,0l0,2l-2.5,0l0,2.5l-2,0l0,-2.5l-2.5,0l0,-2l2.5,0l0,-2.5z"
style="fill:#090909;"/>
</svg>
DEMO BUTTON HOVER...
another
example...
MACOS DROPDOWN...
MacOS
JavaFX
MACOS DROPDOWN...
CODE MACOS DROPDOWN...
public class Demo extends Application {


private Region arrows;


private StackPane arrowButton;


private Label label;


private HBox dropdownBox;


@Override public void init() {


arrows = new Region();


arrows.getStyleClass().add("arrows");


arrowButton = new StackPane(arrows);


arrowButton.getStyleClass().add("arrow-button");


HBox.setHgrow(arrowButton, Priority.NEVER);


HBox.setMargin(arrowButton, new Insets(0, 2, 0, 0));


label = new Label("JavaFX");


label.getStyleClass().add("box-label");


label.setAlignment(Pos.CENTER_LEFT);


HBox.setHgrow(label, Priority.ALWAYS);


dropdownBox = new HBox(5, label, arrowButton);


dropdownBox.getStyleClass().add("dropdown-box");


dropdownBox.setAlignment(Pos.CENTER_RIGHT);


}


@Override public void start(final Stage stage) {


StackPane pane = new StackPane(dropdownBox);


...
.arrow-button StackPane


with .arrows Region childnode
CSS MACOS DROPDOWN...
.root * {


BUTTON-COLOR : rgb(51, 101, 207);


SELECTED-BUTTON-COLOR: derive(BUTTON-COLOR, 10%);


}


.arrow-button {


-fx-min-width : 16px;


-fx-min-height : 16px;


-fx-max-width : 16px;


-fx-max-height : 16px;


-fx-pref-width : 16px;


-fx-pref-height : 16px;


-fx-background-insets: 0px;


-fx-background-radius: 3.25px;


}


3.25px
16px
16px
Set the dimensions and radius for


the .arrow-button StackPane
(StackPane)
CSS MACOS DROPDOWN...
.root * {


BUTTON-COLOR : rgb(51, 101, 207);


SELECTED-BUTTON-COLOR: derive(BUTTON-COLOR, 10%);


}


.arrow-button {


-fx-min-width : 16px;


-fx-min-height : 16px;


-fx-max-width : 16px;


-fx-max-height : 16px;


-fx-pref-width : 16px;


-fx-pref-height : 16px;


-fx-background-insets: 0px;


-fx-background-radius: 3.25px;


-fx-background-color : linear-gradient(to bottom,


derive(BUTTON-COLOR, 20%) 0%,


BUTTON-COLOR 20%,


BUTTON-COLOR 100%)


}


Set the
fi
ll for


the .arrow-button StackPane
(StackPane)
Linear Gradient
CSS MACOS DROPDOWN...
.root * {


BUTTON-COLOR : rgb(51, 101, 207);


SELECTED-BUTTON-COLOR: derive(BUTTON-COLOR, 10%);


}


.arrow-button {


-fx-min-width : 16px;


-fx-min-height : 16px;


-fx-max-width : 16px;


-fx-max-height : 16px;


-fx-pref-width : 16px;


-fx-pref-height : 16px;


-fx-background-insets: 0px, 0.5px;


-fx-background-radius: 3.25px, 2.85px;


-fx-background-color : linear-gradient(to bottom,


derive(BUTTON-COLOR, 20%) 0%,


BUTTON-COLOR 20%,


BUTTON-COLOR 100%),


white;


}


2.85px
Added second layer with
fi
ll color white
(StackPane)
0.5px
CSS MACOS DROPDOWN...
.root * {


BUTTON-COLOR : rgb(51, 101, 207);


SELECTED-BUTTON-COLOR: derive(BUTTON-COLOR, 10%);


}


.arrow-button {


-fx-min-width : 16px;


-fx-min-height : 16px;


-fx-max-width : 16px;


-fx-max-height : 16px;


-fx-pref-width : 16px;


-fx-pref-height : 16px;


-fx-background-insets: 0px, 0.5px;


-fx-background-radius: 3.25px, 2.85px;


-fx-background-color : linear-gradient(to bottom,


derive(BUTTON-COLOR, 20%) 0%,


BUTTON-COLOR 20%,


BUTTON-COLOR 100%),


BUTTON-COLOR;


}


Outer layer
fi
lled with gradient,


inner layer
fi
lled with solid color
Highlight
(StackPane)
CSS MACOS DROPDOWN...
.root * {


BUTTON-COLOR : rgb(51, 101, 207);


SELECTED-BUTTON-COLOR: derive(BUTTON-COLOR, 10%);


}


.arrow-button {


-fx-min-width : 16px;


-fx-min-height : 16px;


-fx-max-width : 16px;


-fx-max-height : 16px;


-fx-pref-width : 16px;


-fx-pref-height : 16px;


-fx-background-insets: 0px, 0.5px;


-fx-background-radius: 3.25px, 2.85px;


-fx-background-color : linear-gradient(to bottom,


derive(BUTTON-COLOR, 20%) 0%,


BUTTON-COLOR 20%,


BUTTON-COLOR 100%),


BUTTON-COLOR;


-fx-effect : dropshadow(two-pass-box, rgba(0, 0, 0, 0.65),


1, 0.0, 0, 0.5);


}


Drop Shadow
Adding a dropshadow
(StackPane)
CSS MACOS DROPDOWN...
.root * {


BUTTON-COLOR : rgb(51, 101, 207);


SELECTED-BUTTON-COLOR: derive(BUTTON-COLOR, 10%);


}


.arrow-button {


-fx-min-width : 16px;


-fx-min-height : 16px;


-fx-max-width : 16px;


-fx-max-height : 16px;


-fx-pref-width : 16px;


-fx-pref-height : 16px;


-fx-padding : 2.5px 4.5px 2.5px 4.5px;


-fx-background-insets: 0px, 0.5px;


-fx-background-radius: 3.25px, 2.85px;


-fx-background-color : linear-gradient(to bottom,


derive(BUTTON-COLOR, 20%) 0%,


BUTTON-COLOR 20%,


BUTTON-COLOR 100%),


BUTTON-COLOR;


-fx-effect : dropshadow(two-pass-box, rgba(0, 0, 0, 0.65),


1, 0.0, 0, 0.5);


}


.arrow-button > .arrows {


-fx-background-insets: 0;


-fx-background-color : white;


-fx-position-shape : true;


-fx-scale-shape : false;


-fx-shape : "M8.047, ... 8.002,2.525Z";


}


4.5px 4.5px
2.5px
2.5px
Adding a SVG shape


to .arrows Region
(StackPane)
(Region)
MACOS DROPDOWN...
MacOS
JavaFX styled
WHEN TO USE CSS...?
Use CSS when...
...you use standard controls


...your control inherits a standard control


...it has an impact on many controls


...the environment is already using CSS


...creating a library and want total control


...the customer should be able to customize the app
back to the
idea...
desktop


app...
gluCOSTATUSFX
Re-styled ToggleButton


using CSS
Icons implemented
using SVGPath
Chart implemented
using Canvas
SWIFT JAVA FX
ToggleButton
HBox ToggleButton ToggleButton
SWIFT JAVA FX
Custom Switch control
SWIFT JAVA FX
SWIFT JAVA FX
SWIFT JAVA FX
SWIFT JAVA FX
TRAYICON
The
Makes use of AWT (EDT* + FXAT**) !!!


Only supports images !!!


Sizes di
ff
er on operating systems


Macos, Windows, Linux***
FXTRAYICON
FXTrayIcon library
*** not all all distributions
** FX Application Thread
* Event Dispatch Thread
Onl
y
images!!!
public BufferedImage createTextTrayIcon(String text, Color color) {
final int width = 64;
final int height = 18;
final double fontSize = 14;
final double x = 32;
final double y = 14;
Canvas canvas = new Canvas(width, height);
GraphicsContext ctx = canvas.getGraphicsContext2D();
ctx.setFont(Fonts.sfProRoundedRegular(fontSize));
ctx.setTextAlign(TextAlignment.CENTER);
ctx.setFill(color);
ctx.fillText(text, x, y);
final WritableImage img = new WritableImage(width, height);
final SnapshotParameters parameters = new SnapshotParameters();
parameters.setFill(Color.TRANSPARENT);
canvas.snapshot(parameters, img);
return SwingFXUtils.fromFXImage(img, null);
}
FXTRAYICON
FXTrayIcon library
Draw text in Canvas node


Take a snapshot of the node


Create a Bu
ff
eredImage


Display the image as tray icon


Sync EDT and FXAT !!!
JAVA FX...?
Can I create that same app in
Yes...!
web...?
jpro
Demo...
DESKTOP JPRO
DESKTOP JPRO
Full size pane instead
of dialog
DESKTOP JPRO
DESKTOP JPRO
DESKTOP JPRO
JPRO APP
Advantages of using JPro
Large parts of the code can be re-used


Performance is good


Easy to start with for Java developers


Runs on every HTML5 capable browser


Is very close to the desktop version


Can run in docker container


Dark/light mode support
JPRO APP
Disadvantages of using JPro
Need a server/cloud infrastructure to run on


Multiuser setup is tricky running on one instance


Dialogs are di
ff
erent from Desktop


No accent color support
Mobile...?
gluon
Demo...
SWIFT JAVA FX
Desktop style buttons
SWIFT JAVA FX
Full size pane instead
of dialog
Desktop style buttons
SWIFT JAVA FX
SWIFT JAVA FX
SWIFT JAVA FX
Desktop style Sliders
GLUON APP
Advantages of using Gluon
Large parts of the code can be re-used


Performance is NOT the problem


Easy to start with for Java developers


Runs on iOS and Android


Can be adjusted for each platform


Can be published on app stores
GLUON APP
Disadvantages of using Gluon
No real native UI out of the box (better on Android)


Problem with 24/7 apps (no native background tasks)


No support for iOS widgets and watch faces


Sound is handled di
ff
erently than on desktop


No accent color support


No dark/light mode support


No automatic locale detection
tip...
Separate
branches
for web +
Mobile
AppleFX
APPLE FX...
Native looking UI's on Macos
APPLE FX...
Native looking UI's on Macos
Demo...
NATIVE UI...
CANVAS
Let's take a look at
CANVAS NODE
Advantages of using Canvas
Just one node


You have "full" control


Fast


Flexible


99% compatible with HTML5 canvas
CANVAS NODE...
Disadvantages of using Canvas
No direct interaction with shapes


Layout is your job (no layout container)


Cleanup and redraw is your job


Not testable


Content is not styleable using CSS*
* partly possible using StyleableProperties
when to
use it...?
CANVAS NODE...
When to use it...
Complex graphics needed


Pixel based graphics needed


Performance needed


No interaction needed


Full control needed


Games


On graphical restricted devices (e.g. Raspberry Pi)
CANVAS NODE...
Examples
Complex Controls
Shape E
ff
ects
CANVAS NODE...
Examples
Pixel based charts
CANVAS NODE...
Examples
Complex Charts
CANVAS NODE...
Examples
Games
CANVAS NODE...
Examples
EXAMPLE
Number of nodes
Label
28 Nodes
TextField
CheckBox
RadioButton
2 Nodes
3 Nodes
3 Nodes
5 Nodes
ComboBox
Button 2 Nodes
NUMBER OF NODES...
NUMBER OF NODES...
Analyse...
Matrix


GridPane


Simple labels


Styled with CSS
NUMBER OF NODES...
NUMBER OF NODES...
saves 86
nodes in 1
control
PERFORMANCE
Some tips about
PERFORMANCE...
Avoid deeply nested layout structures


Reduce number of nodes


Avoid using e
ff
ects


Apply e
ff
ects to groups instead of single nodes


Keep track of dirty state when override layoutChildren()


Use Canvas if needed


Cache nodes before doing animations
Things to keep in mind
PERFORMANCE...
Be aware of FXApplicationThread


Avoid inlining CSS


Know your target platform


Avoid using transparent stages if possible


Disable layout of unused nodes (setManaged(true/false))
Things to keep in mind
MayTheForceBeWithYou II.pdf
MayTheForceBeWithYou II.pdf

Más contenido relacionado

Similar a MayTheForceBeWithYou II.pdf

Patrick Kettner - Creating magic with houdini
Patrick Kettner - Creating magic with houdiniPatrick Kettner - Creating magic with houdini
Patrick Kettner - Creating magic with houdini
OdessaJS Conf
 

Similar a MayTheForceBeWithYou II.pdf (20)

Flash Camp - Degrafa & FXG
Flash Camp - Degrafa & FXGFlash Camp - Degrafa & FXG
Flash Camp - Degrafa & FXG
 
ES6, WTF?
ES6, WTF?ES6, WTF?
ES6, WTF?
 
Introduction to Coding
Introduction to CodingIntroduction to Coding
Introduction to Coding
 
Accelerated Stylesheets
Accelerated StylesheetsAccelerated Stylesheets
Accelerated Stylesheets
 
Patrick Kettner - Creating magic with houdini
Patrick Kettner - Creating magic with houdiniPatrick Kettner - Creating magic with houdini
Patrick Kettner - Creating magic with houdini
 
Start your app the better way with Styled System
Start your app the better way with Styled SystemStart your app the better way with Styled System
Start your app the better way with Styled System
 
Anthony Starks - deck
Anthony Starks - deckAnthony Starks - deck
Anthony Starks - deck
 
Responsive Design for Data Visualization
Responsive Design for Data VisualizationResponsive Design for Data Visualization
Responsive Design for Data Visualization
 
Learn to Love CSS3 [English]
Learn to Love CSS3 [English]Learn to Love CSS3 [English]
Learn to Love CSS3 [English]
 
I Can't Believe It's Not Flash
I Can't Believe It's Not FlashI Can't Believe It's Not Flash
I Can't Believe It's Not Flash
 
CSS3 ...in 3D!
CSS3 ...in 3D!CSS3 ...in 3D!
CSS3 ...in 3D!
 
Creating an Uber Clone - Part IV - Transcript.pdf
Creating an Uber Clone - Part IV - Transcript.pdfCreating an Uber Clone - Part IV - Transcript.pdf
Creating an Uber Clone - Part IV - Transcript.pdf
 
Building a theming system with React - Matteo Ronchi - Codemotion Amsterdam 2017
Building a theming system with React - Matteo Ronchi - Codemotion Amsterdam 2017Building a theming system with React - Matteo Ronchi - Codemotion Amsterdam 2017
Building a theming system with React - Matteo Ronchi - Codemotion Amsterdam 2017
 
Learn Creative Coding: Begin Programming with the Processing Language
Learn Creative Coding: Begin Programming with the Processing LanguageLearn Creative Coding: Begin Programming with the Processing Language
Learn Creative Coding: Begin Programming with the Processing Language
 
Learn Creative Coding: Begin Programming with the Processing Language
Learn Creative Coding: Begin Programming with the Processing LanguageLearn Creative Coding: Begin Programming with the Processing Language
Learn Creative Coding: Begin Programming with the Processing Language
 
CSS3 pronti all'uso
CSS3 pronti all'usoCSS3 pronti all'uso
CSS3 pronti all'uso
 
Learn to love CSS3 | Joomla! Day Deutschland
Learn to love CSS3 | Joomla! Day DeutschlandLearn to love CSS3 | Joomla! Day Deutschland
Learn to love CSS3 | Joomla! Day Deutschland
 
Componentization css angular
Componentization css angularComponentization css angular
Componentization css angular
 
Powerpointpresentation.c
Powerpointpresentation.cPowerpointpresentation.c
Powerpointpresentation.c
 
Emerging Languages: A Tour of the Horizon
Emerging Languages: A Tour of the HorizonEmerging Languages: A Tour of the Horizon
Emerging Languages: A Tour of the Horizon
 

Último

JustNaik Solution Deck (stage bus sector)
JustNaik Solution Deck (stage bus sector)JustNaik Solution Deck (stage bus sector)
JustNaik Solution Deck (stage bus sector)
Max Lee
 

Último (20)

KLARNA - Language Models and Knowledge Graphs: A Systems Approach
KLARNA -  Language Models and Knowledge Graphs: A Systems ApproachKLARNA -  Language Models and Knowledge Graphs: A Systems Approach
KLARNA - Language Models and Knowledge Graphs: A Systems Approach
 
Top Mobile App Development Companies 2024
Top Mobile App Development Companies 2024Top Mobile App Development Companies 2024
Top Mobile App Development Companies 2024
 
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital TransformationWSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
 
Facemoji Keyboard released its 2023 State of Emoji report, outlining the most...
Facemoji Keyboard released its 2023 State of Emoji report, outlining the most...Facemoji Keyboard released its 2023 State of Emoji report, outlining the most...
Facemoji Keyboard released its 2023 State of Emoji report, outlining the most...
 
Studiovity film pre-production and screenwriting software
Studiovity film pre-production and screenwriting softwareStudiovity film pre-production and screenwriting software
Studiovity film pre-production and screenwriting software
 
JustNaik Solution Deck (stage bus sector)
JustNaik Solution Deck (stage bus sector)JustNaik Solution Deck (stage bus sector)
JustNaik Solution Deck (stage bus sector)
 
Workforce Efficiency with Employee Time Tracking Software.pdf
Workforce Efficiency with Employee Time Tracking Software.pdfWorkforce Efficiency with Employee Time Tracking Software.pdf
Workforce Efficiency with Employee Time Tracking Software.pdf
 
Crafting the Perfect Measurement Sheet with PLM Integration
Crafting the Perfect Measurement Sheet with PLM IntegrationCrafting the Perfect Measurement Sheet with PLM Integration
Crafting the Perfect Measurement Sheet with PLM Integration
 
5 Reasons Driving Warehouse Management Systems Demand
5 Reasons Driving Warehouse Management Systems Demand5 Reasons Driving Warehouse Management Systems Demand
5 Reasons Driving Warehouse Management Systems Demand
 
AI/ML Infra Meetup | Reducing Prefill for LLM Serving in RAG
AI/ML Infra Meetup | Reducing Prefill for LLM Serving in RAGAI/ML Infra Meetup | Reducing Prefill for LLM Serving in RAG
AI/ML Infra Meetup | Reducing Prefill for LLM Serving in RAG
 
INGKA DIGITAL: Linked Metadata by Design
INGKA DIGITAL: Linked Metadata by DesignINGKA DIGITAL: Linked Metadata by Design
INGKA DIGITAL: Linked Metadata by Design
 
how-to-download-files-safely-from-the-internet.pdf
how-to-download-files-safely-from-the-internet.pdfhow-to-download-files-safely-from-the-internet.pdf
how-to-download-files-safely-from-the-internet.pdf
 
A Python-based approach to data loading in TM1 - Using Airflow as an ETL for TM1
A Python-based approach to data loading in TM1 - Using Airflow as an ETL for TM1A Python-based approach to data loading in TM1 - Using Airflow as an ETL for TM1
A Python-based approach to data loading in TM1 - Using Airflow as an ETL for TM1
 
AI/ML Infra Meetup | ML explainability in Michelangelo
AI/ML Infra Meetup | ML explainability in MichelangeloAI/ML Infra Meetup | ML explainability in Michelangelo
AI/ML Infra Meetup | ML explainability in Michelangelo
 
A Guideline to Gorgias to to Re:amaze Data Migration
A Guideline to Gorgias to to Re:amaze Data MigrationA Guideline to Gorgias to to Re:amaze Data Migration
A Guideline to Gorgias to to Re:amaze Data Migration
 
StrimziCon 2024 - Transition to Apache Kafka on Kubernetes with Strimzi.pdf
StrimziCon 2024 - Transition to Apache Kafka on Kubernetes with Strimzi.pdfStrimziCon 2024 - Transition to Apache Kafka on Kubernetes with Strimzi.pdf
StrimziCon 2024 - Transition to Apache Kafka on Kubernetes with Strimzi.pdf
 
Agnieszka Andrzejewska - BIM School Course in Kraków
Agnieszka Andrzejewska - BIM School Course in KrakówAgnieszka Andrzejewska - BIM School Course in Kraków
Agnieszka Andrzejewska - BIM School Course in Kraków
 
Implementing KPIs and Right Metrics for Agile Delivery Teams.pdf
Implementing KPIs and Right Metrics for Agile Delivery Teams.pdfImplementing KPIs and Right Metrics for Agile Delivery Teams.pdf
Implementing KPIs and Right Metrics for Agile Delivery Teams.pdf
 
APVP,apvp apvp High quality supplier safe spot transport, 98% purity
APVP,apvp apvp High quality supplier safe spot transport, 98% purityAPVP,apvp apvp High quality supplier safe spot transport, 98% purity
APVP,apvp apvp High quality supplier safe spot transport, 98% purity
 
IT Software Development Resume, Vaibhav jha 2024
IT Software Development Resume, Vaibhav jha 2024IT Software Development Resume, Vaibhav jha 2024
IT Software Development Resume, Vaibhav jha 2024
 

MayTheForceBeWithYou II.pdf

  • 1.
  • 2. Gerrit Grunwald | Developer Advocate | Azul ABOUT ME...
  • 7. SWIFT DESKTOP APP MacOS APP Show value and history Last 30 days average Pattern of last week Time in range Settings Has system tray icon
  • 9. JAVA FX...? Can I create that same app in
  • 11. NATIVE LOOKING WINDOWS Properties Title Buttons for minimize, maximize, close Resizeable Draggable Rounded corners on Macos Support dark and light themes ! Have toolbuttons, text fi elds etc. on Macos !!!
  • 12. NATIVE LOOKING WINDOWS Rounded corners Close, Minimize, Maximize buttons Title
  • 14. CSS So let's try to create such a window using
  • 20. AnchorPane (top) BorderPane Region (center) Region (center) AnchorPane (top) Circle Circle Circle HBox LAYOUT...
  • 21. Height: 52.5px Corner radius: 10px rgb(2, 2, 2) rgb(117, 115, 116) rgb(133, 131, 132) rgb(47, 46, 47) DropShadow DESIGN HEADER...
  • 25. .header { -fx-min-height : 52.5; -fx-max-height : 52.5; -fx-pref-height : 52.5; -fx-background-insets: 0, 0.5 0.5 0 0.5, 1 1 0 1, 1.5 1 0 1; -fx-background-radius: 10 10 0 0, 9.5 9.5 0 0, 9.5 9.5 0 0, 8.5 8.5 0 0; -fx-background-color : rgb(2, 2, 2), linear-gradient(to bottom, rgb(117, 115, 115) 0%, rgb(99, 98, 98) 20%, rgb(99, 98, 98) 100%), rgb(133, 131, 132), rgb(47, 46, 47); -fx-effect : dropshadow(gaussian, rgba(0, 0, 0, 0.35), 1, 0, 0, 1.5) } CSS HEADER... (Zoomed) CSS styled AnchorPane .header
  • 26. public class SimpleHeaderDemo extends Application { private static final String STYLE = "simple-styles.css"; private AnchorPane header; @Override public void init() { header = new AnchorPane(); header.getStyleClass().add("header"); } @Override public void start(final Stage stage) { BorderPane pane = new BorderPane(); pane.setPrefSize(600, 200); pane.setPadding(new Insets(20)); pane.setTop(header); Scene scene = new Scene(pane); scene.getStylesheets() .add(SimpleHeaderDemo.class.getResource(STYLE) .toExternalForm()); stage.setTitle("Header Demo"); stage.setScene(scene); stage.show(); stage.centerOnScreen(); } } CODE HEADER...
  • 27. Corner radius: 10px rgb(2, 2, 2) rgb(84, 82, 81) rgb(32, 34, 34) DESIGN BODY...
  • 28. .body { -fx-background-insets: 0, 0 0.5 0.5 0.5, 0 1 1 1; -fx-background-radius: 0 0 10 10, 0 0 9.5 9.5, 0 0 9.5 9.5; -fx-background-color : rgb(2, 2, 2), rgb(84, 82, 81), rgb(32, 28, 28); } CSS BODY... CSS styled Region .body (Zoomed)
  • 29. public class SimpleHeaderDemo extends Application { private static final String STYLE = "simple-styles.css"; private AnchorPane header; private Region body; @Override public void init() { header = new AnchorPane(); header.getStyleClass().add("header"); body = new Region(); body.getStyleClass().add("body"); } @Override public void start(final Stage stage) { BorderPane pane = new BorderPane(); pane.setPrefSize(400, 400); pane.setPadding(new Insets(20)); pane.setTop(header); pane.setCenter(body); Scene scene = new Scene(pane); scene.getStylesheets() .add(SimpleHeaderDemo.class.getResource(STYLE) .toExternalForm()); stage.setTitle("Header Demo"); stage.setScene(scene); stage.show(); stage.centerOnScreen(); } } CODE .header { -fx-min-height : 52.5; -fx-max-height : 52.5; -fx-pref-height : 52.5; -fx-background-insets: 0, 0.5 0.5 0 0.5, 1 1 0 1, 1.5 1 0 1; -fx-background-radius: 10 10 0 0, 9.5 9.5 0 0, 9.5 9.5 0 0, 8.5 8.5 0 0; -fx-background-color : rgb(2, 2, 2), rgb(133, 131, 132), linear-gradient(to bottom, rgb(117, 115, 115) 0%, rgb(99, 98, 98) 20%, rgb(99, 98, 98) 100%), rgb(47, 46, 47); -fx-effect : dropshadow(gaussian, rgba(0, 0, 0, 0.35), 1, 0, 0, 1.5) } .body { -fx-background-insets: 0, 0 0.5 0.5 0.5, 0 1 1 1; -fx-background-radius: 0 0 10 10, 0 0 9.5 9.5, 0 0 9.5 9.5; -fx-background-color : rgb(2, 2, 2), rgb(84, 82, 81), rgb(32, 28, 28); } CSS
  • 31. Distance: 8px Radius: 6px rgb(236, 107, 95) rgb(244, 190, 79) rgb(91, 87, 87) rgb(38, 193, 56) Distance: 22px DESIGN BUTTONS...
  • 32. public class CircleButton extends Circle { public enum Type { CLOSE("close"), MINIMIZE("minimize"), MAXIMIZE("maximize"); public final String style; Type(final String style) { this.style = style; } } public CircleButton(final Type type) { super(6); getStyleClass().add(type.style); } } CODE BUTTON... .close { -fx-fill : rgb(236, 107, 95); /* RED */ -fx-stroke: derive(rgb(236, 107, 95), -10%); } .minimize { -fx-fill : rgb(244, 190, 79); / * YELLOW */ -fx-stroke: derive(rgb(244, 190, 79), -10%); } .maximize { -fx-fill : rgb(38, 193, 56); /* GREEN */ -fx-stroke: derive(rgb(38, 193, 56), -10%); } .close:disabled, .minimize:disabled, .maximize:disabled { -fx-fill : rgb(91, 87, 87); /* GRAY */ -fx-stroke: derive(rgb(91, 87, 87), -10%); } CSS BUTTON...
  • 33. public class SimpleHeaderDemo extends Application { private static final String STYLE = "simple-styles.css"; private HBox buttonBox; private AnchorPane header; private Region body; @Override public void init() { CircleButton close = new CircleButton(Type.CLOSE); CircleButton minimize = new CircleButton(Type.MINIMIZE); CircleButton maximize = new CircleButton(Type.MAXIMIZE); buttonBox = new HBox(8, close, minimise, maximize); buttonBox.setAlignment(Pos.CENTER); AnchorPane.setTopAnchor(buttonBox, 0d); AnchorPane.setBottomAnchor(buttonBox, 0d); AnchorPane.setLeftAnchor(buttonBox, 22d); header = new AnchorPane(buttonBox); header.getStyleClass().add("header"); body = new Region(); body.getStyleClass().add("body"); } @Override public void start(final Stage stage) {...} } CODE...
  • 35. ORIGINAL JAVA FX stage.initStyle(StageStyle.TRANSPARENT) You need to take care of Resizing + Dragging !!!
  • 39. SHADOWS "Same" code no shadow... Left side shows no shadow Right side shows shadow
  • 41. WRONG ORDER... BorderPane borderPane = new BorderPane(); borderPane.setTop(header); borderPane.setCenter(content); AnchorPane anchorPane = new AnchorPane(header, content); AnchorPane.setTopAnchor(lowerLeftHeader, 0d); AnchorPane.setRightAnchor(lowerLeftHeader, 0d); AnchorPane.setLeftAnchor(lowerLeftHeader, 0d); AnchorPane.setTopAnchor(lowerLeftContent, 50d); AnchorPane.setRightAnchor(lowerLeftContent, 0d); AnchorPane.setLeftAnchor(lowerLeftContent, 0d); 2nd 1st 2nd 1st
  • 42. RIGHT ORDER... BorderPane borderPane = new BorderPane(); borderPane.setCenter(content); borderPane.setTop(header); AnchorPane anchorPane = new AnchorPane(content, header); AnchorPane.setTopAnchor(lowerLeftHeader, 0d); AnchorPane.setRightAnchor(lowerLeftHeader, 0d); AnchorPane.setLeftAnchor(lowerLeftHeader, 0d); AnchorPane.setTopAnchor(lowerLeftContent, 50d); AnchorPane.setRightAnchor(lowerLeftContent, 0d); AnchorPane.setLeftAnchor(lowerLeftContent, 0d); 1st 2nd 1st 2nd
  • 44. BorderPane setE ff ect(new DropShadow()) DropShadow Stage SHADOWS... Custom windows Add the shadow the BorderPane No shadow will show There is no space to draw the shadow
  • 45. SHADOWS... Custom windows Add another Region Keep the Region transparent Add padding to left, right, bottom Add the BorderPane to the Region Apply the shadow to the BorderPane BorderPane setE ff ect(new DropShadow()) DropShadow Stage Transparent Region
  • 48. svg
  • 49. public class CircleButton extends Circle { public enum Type { CLOSE("close"), MINIMIZE("minimize"), MAXIMIZE("maximize"); public final String style; Type(final String style) { this.style = style; } } public CircleButton(final Type type) { super(6); getStyleClass().add(type.style); } } CODE BUTTON... extends Circle
  • 50. public class CircleButton extends StackPane { public enum Type { CLOSE("close"), MINIMIZE("minimize"), MAXIMIZE("maximize"); public final String style; Type(final String style) { this.style = style; } } private final Region icon; public CircleButton(final Type type) { super(); icon.getStyleClass().add("icon") getChildren().setAll(icon); getStyleClass().add(type.style); } } CODE BUTTON... extends StackPane Region icon
  • 51. .close:hover .icon { -fx-scale-shape : false; -fx-shape : "M 2,2.5 l 2,0 l 0,2.5 l 2.5,0 l 0,2 l -2.5,0 l 0,2.5 l -2,0 l 0,-2.5 l -2.5,0 l 0,-2 l 2.5,0 l 0,-2.5 z"; } CSS BUTTON... adding points to the SVG shape...
  • 52. .close:hover .icon { -fx-background-color: rgb(55, 52, 52); -fx-scale-shape : false; -fx-shape : "M 2,2.5 l 2,0 l 0,2.5 l 2.5,0 l 0,2 l -2.5,0 l 0,2.5 l -2,0 l 0,-2.5 l -2.5,0 l 0,-2 l 2.5,0 l 0,-2.5 z"; } CSS BUTTON... set the fi ll color
  • 53. .close:hover .icon { -fx-rotate : 45; -fx-background-color: rgb(55, 52, 52); -fx-scale-shape : false; -fx-shape : "M 2,2.5 l 2,0 l 0,2.5 l 2.5,0 l 0,2 l -2.5,0 l 0,2.5 l -2,0 l 0,-2.5 l -2.5,0 l 0,-2 l 2.5,0 l 0,-2.5 z"; } CSS BUTTON... rotate the shape by 45°
  • 54. USE VECTOR DRAWING PROGRAM... <?xml version="1.0" encoding="UTF-8" standalone="no"?> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/ svg11.dtd"> <svg width="12px" height="12px" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http:// www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke- miterlimit:2;"> <path d="M5,2.5l2,0l0,2.5l2.5,0l0,2l-2.5,0l0,2.5l-2,0l0,-2.5l-2.5,0l0,-2l2.5,0l0,-2.5z" style="fill:#090909;"/> </svg>
  • 59. CODE MACOS DROPDOWN... public class Demo extends Application { private Region arrows; private StackPane arrowButton; private Label label; private HBox dropdownBox; @Override public void init() { arrows = new Region(); arrows.getStyleClass().add("arrows"); arrowButton = new StackPane(arrows); arrowButton.getStyleClass().add("arrow-button"); HBox.setHgrow(arrowButton, Priority.NEVER); HBox.setMargin(arrowButton, new Insets(0, 2, 0, 0)); label = new Label("JavaFX"); label.getStyleClass().add("box-label"); label.setAlignment(Pos.CENTER_LEFT); HBox.setHgrow(label, Priority.ALWAYS); dropdownBox = new HBox(5, label, arrowButton); dropdownBox.getStyleClass().add("dropdown-box"); dropdownBox.setAlignment(Pos.CENTER_RIGHT); } @Override public void start(final Stage stage) { StackPane pane = new StackPane(dropdownBox); ... .arrow-button StackPane with .arrows Region childnode
  • 60. CSS MACOS DROPDOWN... .root * { BUTTON-COLOR : rgb(51, 101, 207); SELECTED-BUTTON-COLOR: derive(BUTTON-COLOR, 10%); } .arrow-button { -fx-min-width : 16px; -fx-min-height : 16px; -fx-max-width : 16px; -fx-max-height : 16px; -fx-pref-width : 16px; -fx-pref-height : 16px; -fx-background-insets: 0px; -fx-background-radius: 3.25px; } 3.25px 16px 16px Set the dimensions and radius for the .arrow-button StackPane (StackPane)
  • 61. CSS MACOS DROPDOWN... .root * { BUTTON-COLOR : rgb(51, 101, 207); SELECTED-BUTTON-COLOR: derive(BUTTON-COLOR, 10%); } .arrow-button { -fx-min-width : 16px; -fx-min-height : 16px; -fx-max-width : 16px; -fx-max-height : 16px; -fx-pref-width : 16px; -fx-pref-height : 16px; -fx-background-insets: 0px; -fx-background-radius: 3.25px; -fx-background-color : linear-gradient(to bottom, derive(BUTTON-COLOR, 20%) 0%, BUTTON-COLOR 20%, BUTTON-COLOR 100%) } Set the fi ll for the .arrow-button StackPane (StackPane) Linear Gradient
  • 62. CSS MACOS DROPDOWN... .root * { BUTTON-COLOR : rgb(51, 101, 207); SELECTED-BUTTON-COLOR: derive(BUTTON-COLOR, 10%); } .arrow-button { -fx-min-width : 16px; -fx-min-height : 16px; -fx-max-width : 16px; -fx-max-height : 16px; -fx-pref-width : 16px; -fx-pref-height : 16px; -fx-background-insets: 0px, 0.5px; -fx-background-radius: 3.25px, 2.85px; -fx-background-color : linear-gradient(to bottom, derive(BUTTON-COLOR, 20%) 0%, BUTTON-COLOR 20%, BUTTON-COLOR 100%), white; } 2.85px Added second layer with fi ll color white (StackPane) 0.5px
  • 63. CSS MACOS DROPDOWN... .root * { BUTTON-COLOR : rgb(51, 101, 207); SELECTED-BUTTON-COLOR: derive(BUTTON-COLOR, 10%); } .arrow-button { -fx-min-width : 16px; -fx-min-height : 16px; -fx-max-width : 16px; -fx-max-height : 16px; -fx-pref-width : 16px; -fx-pref-height : 16px; -fx-background-insets: 0px, 0.5px; -fx-background-radius: 3.25px, 2.85px; -fx-background-color : linear-gradient(to bottom, derive(BUTTON-COLOR, 20%) 0%, BUTTON-COLOR 20%, BUTTON-COLOR 100%), BUTTON-COLOR; } Outer layer fi lled with gradient, inner layer fi lled with solid color Highlight (StackPane)
  • 64. CSS MACOS DROPDOWN... .root * { BUTTON-COLOR : rgb(51, 101, 207); SELECTED-BUTTON-COLOR: derive(BUTTON-COLOR, 10%); } .arrow-button { -fx-min-width : 16px; -fx-min-height : 16px; -fx-max-width : 16px; -fx-max-height : 16px; -fx-pref-width : 16px; -fx-pref-height : 16px; -fx-background-insets: 0px, 0.5px; -fx-background-radius: 3.25px, 2.85px; -fx-background-color : linear-gradient(to bottom, derive(BUTTON-COLOR, 20%) 0%, BUTTON-COLOR 20%, BUTTON-COLOR 100%), BUTTON-COLOR; -fx-effect : dropshadow(two-pass-box, rgba(0, 0, 0, 0.65), 1, 0.0, 0, 0.5); } Drop Shadow Adding a dropshadow (StackPane)
  • 65. CSS MACOS DROPDOWN... .root * { BUTTON-COLOR : rgb(51, 101, 207); SELECTED-BUTTON-COLOR: derive(BUTTON-COLOR, 10%); } .arrow-button { -fx-min-width : 16px; -fx-min-height : 16px; -fx-max-width : 16px; -fx-max-height : 16px; -fx-pref-width : 16px; -fx-pref-height : 16px; -fx-padding : 2.5px 4.5px 2.5px 4.5px; -fx-background-insets: 0px, 0.5px; -fx-background-radius: 3.25px, 2.85px; -fx-background-color : linear-gradient(to bottom, derive(BUTTON-COLOR, 20%) 0%, BUTTON-COLOR 20%, BUTTON-COLOR 100%), BUTTON-COLOR; -fx-effect : dropshadow(two-pass-box, rgba(0, 0, 0, 0.65), 1, 0.0, 0, 0.5); } .arrow-button > .arrows { -fx-background-insets: 0; -fx-background-color : white; -fx-position-shape : true; -fx-scale-shape : false; -fx-shape : "M8.047, ... 8.002,2.525Z"; } 4.5px 4.5px 2.5px 2.5px Adding a SVG shape to .arrows Region (StackPane) (Region)
  • 67. WHEN TO USE CSS...? Use CSS when... ...you use standard controls ...your control inherits a standard control ...it has an impact on many controls ...the environment is already using CSS ...creating a library and want total control ...the customer should be able to customize the app
  • 71. Re-styled ToggleButton using CSS Icons implemented using SVGPath Chart implemented using Canvas SWIFT JAVA FX ToggleButton HBox ToggleButton ToggleButton
  • 72. SWIFT JAVA FX Custom Switch control
  • 78. Makes use of AWT (EDT* + FXAT**) !!! Only supports images !!! Sizes di ff er on operating systems Macos, Windows, Linux*** FXTRAYICON FXTrayIcon library *** not all all distributions ** FX Application Thread * Event Dispatch Thread
  • 80. public BufferedImage createTextTrayIcon(String text, Color color) { final int width = 64; final int height = 18; final double fontSize = 14; final double x = 32; final double y = 14; Canvas canvas = new Canvas(width, height); GraphicsContext ctx = canvas.getGraphicsContext2D(); ctx.setFont(Fonts.sfProRoundedRegular(fontSize)); ctx.setTextAlign(TextAlignment.CENTER); ctx.setFill(color); ctx.fillText(text, x, y); final WritableImage img = new WritableImage(width, height); final SnapshotParameters parameters = new SnapshotParameters(); parameters.setFill(Color.TRANSPARENT); canvas.snapshot(parameters, img); return SwingFXUtils.fromFXImage(img, null); } FXTRAYICON FXTrayIcon library Draw text in Canvas node Take a snapshot of the node Create a Bu ff eredImage Display the image as tray icon Sync EDT and FXAT !!!
  • 81. JAVA FX...? Can I create that same app in
  • 84. jpro
  • 87. DESKTOP JPRO Full size pane instead of dialog
  • 91. JPRO APP Advantages of using JPro Large parts of the code can be re-used Performance is good Easy to start with for Java developers Runs on every HTML5 capable browser Is very close to the desktop version Can run in docker container Dark/light mode support
  • 92. JPRO APP Disadvantages of using JPro Need a server/cloud infrastructure to run on Multiuser setup is tricky running on one instance Dialogs are di ff erent from Desktop No accent color support
  • 94. gluon
  • 96. SWIFT JAVA FX Desktop style buttons
  • 97. SWIFT JAVA FX Full size pane instead of dialog Desktop style buttons
  • 100. SWIFT JAVA FX Desktop style Sliders
  • 101. GLUON APP Advantages of using Gluon Large parts of the code can be re-used Performance is NOT the problem Easy to start with for Java developers Runs on iOS and Android Can be adjusted for each platform Can be published on app stores
  • 102. GLUON APP Disadvantages of using Gluon No real native UI out of the box (better on Android) Problem with 24/7 apps (no native background tasks) No support for iOS widgets and watch faces Sound is handled di ff erently than on desktop No accent color support No dark/light mode support No automatic locale detection
  • 103. tip...
  • 106. APPLE FX... Native looking UI's on Macos
  • 107. APPLE FX... Native looking UI's on Macos
  • 111. CANVAS NODE Advantages of using Canvas Just one node You have "full" control Fast Flexible 99% compatible with HTML5 canvas
  • 112. CANVAS NODE... Disadvantages of using Canvas No direct interaction with shapes Layout is your job (no layout container) Cleanup and redraw is your job Not testable Content is not styleable using CSS* * partly possible using StyleableProperties
  • 114. CANVAS NODE... When to use it... Complex graphics needed Pixel based graphics needed Performance needed No interaction needed Full control needed Games On graphical restricted devices (e.g. Raspberry Pi)
  • 117. Pixel based charts CANVAS NODE... Examples
  • 121. Label 28 Nodes TextField CheckBox RadioButton 2 Nodes 3 Nodes 3 Nodes 5 Nodes ComboBox Button 2 Nodes NUMBER OF NODES...
  • 125. saves 86 nodes in 1 control
  • 127. PERFORMANCE... Avoid deeply nested layout structures Reduce number of nodes Avoid using e ff ects Apply e ff ects to groups instead of single nodes Keep track of dirty state when override layoutChildren() Use Canvas if needed Cache nodes before doing animations Things to keep in mind
  • 128. PERFORMANCE... Be aware of FXApplicationThread Avoid inlining CSS Know your target platform Avoid using transparent stages if possible Disable layout of unused nodes (setManaged(true/false)) Things to keep in mind