您始终可以使用具有该功能的Swing来以旧方式进行操作。
而Swing允许您嵌入JavaFX。当然,最好有
一个没有Swing的干净机制,但是afaik它尚不存在(尚未)。
Example:
import javafx.application.Platform;import javafx.embed.swing.JFXPanel;import javafx.scene.Scene;import javafx.scene.control.ContextMenu;import javafx.scene.control.Label;import javafx.scene.control.MenuItem;import javafx.scene.layout.Background;import javafx.scene.layout.StackPane;import javafx.scene.paint.Color;import javafx.scene.paint.CycleMethod;import javafx.scene.paint.RadialGradient;import javafx.scene.paint.Stop;import javax.swing.Jframe;import javax.swing.SwingUtilities;import java.awt.geom.GeneralPath;public class Widget extends Jframe { class DragContext { double x; double y; } public Widget() { // decoration setType(Type.UTILITY); setUndecorated(true); setSize(200, 200); toBack(); // position // setLocation(100, 100); setLocationRelativeTo(null); // centers on screen // frame operations setDefaultCloseOperation(Jframe.EXIT_ON_CLOSE); // frame shape (a star) double points[][] = { { 0, 85 }, { 75, 75 }, { 100, 10 }, { 125, 75 }, { 200, 85 }, { 150, 125 }, { 160, 190 }, { 100, 150 }, { 40, 190 }, { 50, 125 }, { 0, 85 } }; GeneralPath star = new GeneralPath(); star.moveTo(points[0][0], points[0][1]); for (int k = 1; k < points.length; k++) star.lineTo(points[k][0], points[k][2]); star.closePath(); setShape(star); // embed fx into swing JFXPanel fxPanel = new JFXPanel(); Widget.this.getContentPane().add(fxPanel); Platform.runLater(new Runnable() { @Override public void run() { // set scene in JFXPanel fxPanel.setScene( createFxScene()); // show frame SwingUtilities.invokeLater(new Runnable() { @Override public void run() { Widget.this.setVisible(true); // send it to the desktop, behind all other existing windows // Widget.this.toBack(); // Widget.this.repaint(); } }); } }); } private Scene createFxScene() { StackPane rootPane = new StackPane(); rootPane.setBackground(Background.EMPTY); // add some node Label label = new Label("Bright & Shiny"); label.setTextFill(Color.RED); rootPane.getChildren().add(label); // create scene Scene scene = new Scene(rootPane); // gradient fill RadialGradient radialGradient = new RadialGradient( 270, 0.8, 0.5, 0.5, 0.7, true, CycleMethod.NO_CYCLE, new Stop( .5f, Color.YELLOW), new Stop( .7f, Color.ORANGE), new Stop( .9f, Color.ORANGERED)); scene.setFill(radialGradient); // context menu with close button ContextMenu contextMenu = new ContextMenu(); MenuItem closeMenuItem = new MenuItem("Close"); closeMenuItem.setonAction(actionEvent -> System.exit(0)); contextMenu.getItems().add(closeMenuItem); // set context menu for scene scene.setonMousePressed(mouseEvent -> { if (mouseEvent.isSecondaryButtonDown()) { contextMenu.show(rootPane, mouseEvent.getScreenX(), mouseEvent.getScreenY()); } }); // allow the frame to be dragged around final DragContext dragDelta = new DragContext(); rootPane.setonMousePressed(mouseEvent -> { dragDelta.x = Widget.this.getLocation().getX() - mouseEvent.getScreenX(); dragDelta.y = Widget.this.getLocation().getY() - mouseEvent.getScreenY(); }); rootPane.setonMouseDragged(mouseEvent -> Widget.this.setLocation((int) (mouseEvent.getScreenX() + dragDelta.x), (int) (mouseEvent.getScreenY() + dragDelta.y))); return scene; } public static void main(String[] args) { new Widget(); }}这是未显示在任务栏中的窗口小部件的屏幕快照。
用鼠标左键将其拖动。鼠标右键提供带有
关闭按钮的上下文菜单。
小部件
上面的代码使用秋千框架的形状。下面的代码使用javafx控件的形状。
这是一个只有控件可见的版本。我使用反射标签控件。
如果要将控件直接发送到桌面,则需要激活toBack()调用。您可以使用鼠标滚轮缩放控件。在最大变焦大小限制为Jframe的大小。
您需要为自定义控件做的就是在createFxControl()中实现代码
import javafx.application.Platform;import javafx.embed.swing.JFXPanel;import javafx.event.EventHandler;import javafx.scene.Scene;import javafx.scene.control.ContextMenu;import javafx.scene.control.Control;import javafx.scene.control.Label;import javafx.scene.control.MenuItem;import javafx.scene.effect.Reflection;import javafx.scene.input.ScrollEvent;import javafx.scene.layout.Background;import javafx.scene.layout.StackPane;import javafx.scene.paint.Color;import javafx.scene.text.Font;import javax.swing.Jframe;import javax.swing.SwingUtilities;public class LabelWidget extends Jframe { class DragContext { double x; double y; } public LabelWidget() { // decoration setType(Type.UTILITY); setUndecorated(true); // make frame transparent, we only want the control to be visible setBackground(new java.awt.Color(0,0,0,0)); setSize(400, 400); // position // setLocation(100, 100); setLocationRelativeTo(null); // centers on screen // frame operations setDefaultCloseOperation(Jframe.EXIT_ON_CLOSE); // embed fx into swing JFXPanel fxPanel = new JFXPanel(); LabelWidget.this.getContentPane().add(fxPanel); Platform.runLater(new Runnable() { @Override public void run() { // set scene in JFXPanel fxPanel.setScene( createFxScene()); // show frame SwingUtilities.invokeLater(new Runnable() { @Override public void run() { LabelWidget.this.setVisible(true); // send it to the desktop, behind all other existing windows // ClockWidget.this.toBack(); // ClockWidget.this.repaint(); } }); } }); } private Scene createFxScene() { StackPane rootPane = new StackPane(); // make pane transparent, we only want the control to be visible rootPane.setBackground(Background.EMPTY); // add control Control control = createFxControl(); rootPane.getChildren().add( control); // create scene Scene scene = new Scene(rootPane); // make scene transparent, we only want the control to be visible scene.setFill( Color.TRANSPARENT); // context menu with close button ContextMenu contextMenu = new ContextMenu(); MenuItem closeMenuItem = new MenuItem("Close"); closeMenuItem.setonAction(actionEvent -> System.exit(0)); contextMenu.getItems().add(closeMenuItem); control.setContextMenu(contextMenu); // allow the frame to be dragged around makeDraggable( control); // allow zooming makeZoomable( control); return scene; } private Control createFxControl() { Label label = new Label( "I'm a Label"); label.setFont(new Font("Tahoma", 24)); label.setEffect(new Reflection()); return label; } public void makeDraggable( Control control) { final DragContext dragDelta = new DragContext(); control.setonMousePressed(mouseEvent -> { dragDelta.x = LabelWidget.this.getLocation().getX() - mouseEvent.getScreenX(); dragDelta.y = LabelWidget.this.getLocation().getY() - mouseEvent.getScreenY(); }); control.setonMouseDragged(mouseEvent -> LabelWidget.this.setLocation((int) (mouseEvent.getScreenX() + dragDelta.x), (int) (mouseEvent.getScreenY() + dragDelta.y))); } public void makeZoomable( Control control) { // note: in order to make it larger, we'd have to resize the stage/frame => we limit the size to 1.0 for now and allow only making the control smaller final double MAX_SCALE = 1.0; final double MIN_SCALE = 0.1; control.addEventFilter(ScrollEvent.ANY, new EventHandler<ScrollEvent>() { @Override public void handle(ScrollEvent event) { double delta = 1.2; double scale = control.getScaleX(); if (event.getDeltaY() < 0) { scale /= delta; } else { scale *= delta; } scale = clamp(scale, MIN_SCALE, MAX_SCALE); control.setScaleX(scale); control.setScaleY(scale); event.consume(); } }); } public static double clamp( double value, double min, double max) { if( Double.compare(value, min) < 0) return min; if( Double.compare(value, max) > 0) return max; return value; } public static void main(String[] args) { new LabelWidget(); }}Or if you have the awesome Enzo library from https://github.com/HanSolo/Enzo
at hand, you can use this pre:
private Control createFxControl() { // create a clock using the enzo library from https://github.com/HanSolo/Enzo Clock clock = ClockBuilder.create() // .prefSize(400, 400) .design(Clock.Design.DB) .running(true) .text("Berlin") .autonightMode(true) .build(); return clock;}to create this:



