Erstellen Sie in JavaFX ein rahmenloses, nicht rechteckiges Fenster ohne Taskleiste

Ein Hinweis auf Versuch und Irrtum beim Versuch, eine JavaFX-Anwendung zu erstellen, die nicht in der Taskleiste angezeigt wird, z. B. Desktop-Zubehör, ohne Rand und nicht quadratisch.

Umgebung

OS Windows 10

Java 1.8.0_162

Fensteranzeige ohne Taskleiste

package sample.javafx;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
import javafx.stage.StageStyle;

public class Main extends Application {
    
    public static void main(String[] args) {
        Application.launch(args);
    }

    @Override
    public void start(Stage primaryStage) throws Exception {
        primaryStage.initStyle(StageStyle.UTILITY);
        Parent root = FXMLLoader.load(this.getClass().getResource("/main.fxml"));
        primaryStage.setScene(new Scene(root));
        primaryStage.show();
    }
}

** Ausführungsergebnis **

javafx.jpg

Erläuterung

Anzeigen eines nicht rechteckigen Fensters ohne Rahmen

main.fxml

javafx.jpg

package sample.javafx;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javafx.stage.StageStyle;

public class Main extends Application {
    
    public static void main(String[] args) {
        Application.launch(args);
    }

    @Override
    public void start(Stage primaryStage) throws Exception {
        primaryStage.initStyle(StageStyle.TRANSPARENT);

        Parent root = FXMLLoader.load(this.getClass().getResource("/main.fxml"));
        Scene scene = new Scene(root);
        scene.setFill(Color.TRANSPARENT);
        primaryStage.setScene(scene);

        primaryStage.show();
    }
}

** Ausführungsergebnis **

javafx.jpg

Erläuterung

Kombinieren Sie die beiden

UTILITY TRANSPARENT
Taskleiste ausblenden OK NG
Nicht rechteckiges Fenster NG OK

Auf diese Weise verfügt jeder über die gewünschten Funktionen und die Funktionen, die Sie nicht benötigen. Wenn Sie also dort oben stehen, können Sie nicht aufstehen. Ab April 2018 scheint es keine Möglichkeit zu geben, diese beiden ordentlich zu kombinieren.

In der OpenJDK-Ausgabe wird dieses Problem erwähnt, es wurde jedoch zuletzt im Mai 2017 aktualisiert, und seitdem scheint es keine Fortschritte zu geben.

[JDK-8091566] Taskbar-less Undecorated Transparent Window - Java Bug System

Zwangsweise kombinieren

Wie in der obigen Ausgabe erwähnt, können Sie beide zwangsweise kombinieren.

Insbesondere ist es wie folgt.

Das heißt, die primäre Stufe wird nur verwendet, um die Funktion "UTILITY" zu verwenden, die die Taskleiste verbirgt und vom Bildschirm ausgeblendet wird, und das tatsächlich sichtbare Fenster wird von einer anderen "Stufe" mit der Einstellung "TRANSPARENT" ausgeführt. Die Methode.

javafx.jpg

Die Bedenken dieser Methode werden in der obigen Ausgabe wie folgt erläutert:

This is a dangerous hack because that UTILITY window could get placed back on the main screen if the computer screen resizes like from a remote desktop session connect and the OS decides to place all windows back on the visible bounds. Tests have shown this doesn't happen, but it feels like it could in certain cases.

(Übersetzung) Dies ist ein gefährlicher Hack. Dies liegt daran, dass das UTILITY-Fenster möglicherweise zum Hauptfenster zurückkehrt, wenn die Größe des Computerbildschirms geändert wird, z. B. durch Verbinden einer Remotedesktopsitzung, und das Betriebssystem beschließt, alle Fensterpositionen in den sichtbaren Bereich zurückzusetzen. Tests sagen, dass dies nicht passiert, aber ich denke, dass es in bestimmten Fällen wahrscheinlich ist.

Es scheint, dass es im Test nicht passiert, aber es scheint, dass es keine saubere Lösung ist. Es ist leicht vorstellbar, dass wenn etwas schief geht und die Primärstufe sichtbar ist, es ziemlich hässlich wird.

Um dieses Problem zu umgehen, habe ich auch die Primärstufe "Deckkraft" auf "0" gesetzt. Wenn die Umgebung "Deckkraft" unterstützt, ist die Primärstufe nicht sichtbar, wenn sie versehentlich in den sichtbaren Bereich eintritt. In einer Umgebung, in der "Deckkraft" nicht unterstützt wird, ist dies jedoch nicht sinnvoll. Ich denke, es wird notwendig sein, sie vom Bildschirm zu entfernen.

Finale Form

Zusätzlich zu der oben erwähnten erzwungenen Kombination ist das Endergebnis wie folgt, wenn die Implementierung wie die Taskleiste enthalten ist.

main.fxml

javafx.jpg

Main.java


package sample.javafx;

import javafx.application.Application;
import javafx.application.Platform;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javafx.stage.StageStyle;

import javax.imageio.ImageIO;
import java.awt.TrayIcon;
import java.awt.SystemTray;
import java.awt.AWTException;
import java.awt.image.BufferedImage;
import java.io.IOException;

public class Main extends Application {

    private TrayIcon trayIcon;
    
    public static void main(String[] args) {
        Application.launch(args);
    }

    @Override
    public void start(Stage primaryStage) throws Exception {
        Platform.setImplicitExit(false);
        
        this.initPrimaryStage(primaryStage);
        Stage mainStage = this.initMainStage(primaryStage);
        this.initSystemTray(mainStage);
        
        primaryStage.show();
        mainStage.show();
    }
    
    private void initPrimaryStage(Stage primaryStage) {
        primaryStage.initStyle(StageStyle.UTILITY);
        primaryStage.setOpacity(0.0);
        primaryStage.setX(-1000);
        primaryStage.setY(-1000);
    }
    
    private Stage initMainStage(Stage primaryStage) throws IOException {
        Stage mainStage = new Stage();
        mainStage.initOwner(primaryStage);
        mainStage.initStyle(StageStyle.TRANSPARENT);
        
        FXMLLoader fxmlLoader = new FXMLLoader(this.getClass().getResource("/main.fxml"));
        Parent root = fxmlLoader.load();
        Scene scene = new Scene(root);
        scene.setFill(Color.TRANSPARENT);
        mainStage.setScene(scene);

        MainController controller = fxmlLoader.getController();
        controller.setStage(mainStage);

        return mainStage;
    }
    
    private void initSystemTray(Stage mainStage) throws IOException, AWTException {
        if (!SystemTray.isSupported()) {
            return;
        }
        
        BufferedImage img = ImageIO.read(this.getClass().getResource("/img/open.png "));
        this.trayIcon = new TrayIcon(img);
        this.trayIcon.setImageAutoSize(true);
        this.trayIcon.addActionListener(e -> {
            Platform.runLater(() -> {
                if (mainStage.isShowing()) {
                    mainStage.hide();
                } else {
                    mainStage.show();
                }
            });
        });
        this.trayIcon.setToolTip("show/hide");
        SystemTray systemTray = SystemTray.getSystemTray();
        systemTray.add(trayIcon);
    }

    @Override
    public void stop() {
        if (SystemTray.isSupported() && this.trayIcon != null) {
            SystemTray.getSystemTray().remove(this.trayIcon);
        }
    }
}

MainController.java


package sample.javafx;

import javafx.application.Platform;
import javafx.fxml.FXML;
import javafx.scene.input.MouseEvent;
import javafx.stage.Stage;

public class MainController {
    private Stage stage;
    private double mouseOffsetX;
    private double mouseOffsetY;

    public void setStage(Stage stage) {
        this.stage = stage;
    }

    @FXML
    public void close() {
        Platform.exit();
    }

    @FXML
    public void onMousePressed(MouseEvent event) {
        this.mouseOffsetX = this.stage.getX() - event.getScreenX();
        this.mouseOffsetY = this.stage.getY() - event.getScreenY();
    }
    
    @FXML
    public void onMouseDragged(MouseEvent event) {
        this.stage.setX(event.getScreenX() + this.mouseOffsetX);
        this.stage.setY(event.getScreenY() + this.mouseOffsetY);
    }
}

** Ausführungsergebnis **

Es sieht so aus, als würden Sie ziehen

javafx.gif

Es sieht so aus, als ob es sich in der Taskleiste befindet

javafx.png

Erläuterung

Main.java


    @Override
    public void start(Stage primaryStage) throws Exception {
        Platform.setImplicitExit(false);

** Verwendung der Taskleiste mit JavaFX **

Recommended Posts

Erstellen Sie in JavaFX ein rahmenloses, nicht rechteckiges Fenster ohne Taskleiste
Erstellen Sie eine Datenbank in einer Produktionsumgebung
Erstellen Sie ein Servlet-Programm in Eclipse
Erstellen wir eine Taschenrechner-App mit Java ~ Erstellen Sie einen Anzeigebereich im Fenster
[Android] Erstellen Sie ein Schiebemenü ohne Verwendung der Navigationsansicht
Erstellen Sie eine CSR mit erweiterten Informationen in Java
Erstellen Sie in Eclipse ein einfaches Stapelverarbeitungsframework.
Versuchen Sie, ein Bulletin Board in Java zu erstellen
Erstellen Sie mit SwiftUI 2.0 eine benutzerdefinierte Registerkartenansicht
Lassen Sie uns mit Java ein supereinfaches Webframework erstellen
So erstellen Sie ein Thema in Liferay 7 / DXP
So erstellen Sie einfach ein Pulldown mit Rails
Docker-Befehl zum Erstellen eines Rails-Projekts in einem einzigen Schlag in einer Umgebung ohne Ruby