当前位置: 首页 > 面试题库 >

javafx中是否可以有一个透明的实用程序阶段?

殳越
2023-03-14
问题内容

我知道您可以设置一个具有实用程序样式
“ Stage.InitStyle(StageStyle.UTILITY);”的舞台。并且您可以将其设置为具有
透明样式“ Stage.InitStyle(StageStyle.TRANSPARENT);” 但是你们
两个可以在同一阶段吗?我很累,所以舞台不会
在开始菜单中显示为向下的窗口,我希望舞台不可见,
以便您只能看到场景。


问题答案:

您始终可以使用具有该功能的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;
    }
    /**
     * Create the JavaFX control of which we use the shape.
     * @return
     */
    private Control createFxControl() {

        Label label = new Label( "I'm a Label");
        label.setFont(new Font("Tahoma", 24));
        label.setEffect(new Reflection());

        return label;
    }



    /**
     * Allow dragging of the stage / control on the desktop
     * @param control
     * @param stage
     */
    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)));

    }

    /**
     * Allow zooming
     * @param control
     */
    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();
            }
        });

    }

    /**
     * Limit bounds of value
     * @param value
     * @param min
     * @param max
     * @return
     */
    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 code:

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:

enter image description here



 类似资料:
  • 问题内容: 使用jdk1.6.0_26我似乎能够对JFrame应用半透明,但对于jre7则不是这样: NativeException:java.awt.IllegalComponentStateException:装饰框架 ex(jruby脚本编写Java,但jdk1.6不适用于jdk7): 所以我的问题是“ jdk7中是否可以有一个半透明的标题栏”(我希望创建的透明窗口可拖动/可调整大小) 问题

  • 问题内容: 我喜欢旧的Java小程序。但是因为我真的很喜欢JFX的工作方式,所以我想使用JFX编写一些游戏(甚至是游戏制作系统,谁知道?),但是我希望能够将它们发布到我的网站上。人们将如何去做呢? 问题答案: 是的,您应该可以将JavaFX嵌入到您的网页中: http://docs.oracle.com/javase/8/docs/technotes/guides/deploy/deploymen

  • 我给自己写了一个实用程序来将列表分成给定大小的批次。我只是想知道是否已经有任何apache公共资源用于此。 请让我知道是否有任何现有的实用程序已经相同。

  • 我正在使用本机绑定javafx maven插件。在构建本机包时,在包阶段,会为我的应用程序创建一个.app和.dmg。当执行本机包时,会同时创建.app和.dmg。之后,我的资源插件从另一个项目复制一个插件到这个项目的.app。但问题是,插件被复制到.app而不是.dmg上,因为.dmg已经创建了。我的要求是:我想要在相同的包阶段内有一些秩序,即首先我想要我的.app被创建,然后我想要插件被复制,

  • 这个问题很简单,在javafx 2.2中的一个阶段,最大化不是一个选项(通过从菜单栏中删除控件),但需要允许最小化,是否可以在代码中取消最小化阶段? 我尝试过的事情(我可以访问静态阶段): Platform.runLater(new Runnable(){public ull run(){ stage.show();stage.requestFocus();stage.toFront();stag