Affichage de l'icône dans la barre d'état système en Java (Windows: zone de notification / Mac: barre de menus)

introduction

Récemment (dans mon domaine de passe-temps), j'écris souvent beaucoup de code côté serveur en utilisant le framework Java Spring Boot, mais j'ai soudainement voulu afficher une icône dans la barre d'état système et la rendre résidente. Compte tenu de la distribution d'applications de type serveur à des personnes non liées aux systèmes d'information, j'ai pensé qu'il ne serait pas convivial d'afficher une console telle qu'un terminal, et j'ai pensé que ce serait bien si l'opération minimale pouvait être effectuée avec l'icône dans la barre d'état système. Est le déclencheur.

La barre d'état système mentionnée dans cet article est la partie rouge de l'image ci-dessous.

システムトレイ

Il s'agit de la "zone de notification" sous Windows et de la "barre de menu" sous Mac. Je pense qu'il y en a des similaires dans d'autres systèmes d'exploitation. (Actuellement, Windows n'est plus appelé une barre des tâches ...)

environnement

Cette fois, je vais l'essayer avec deux OS.

ÉTAPE 1: Éteignez l'icône pour le moment

Dans cet article, l'illustration du caractère "A" d'Irasutoya-sama est utilisée comme icône d'exemple ʻicon.png`.

Tout d'abord, le code qui met juste une icône.

code

IconDemo.java



import java.awt.AWTException;
import java.awt.Image;
import java.awt.SystemTray;
import java.awt.Toolkit;
import java.awt.TrayIcon;

public class IconDemo {

    public static void main(String[] args) {
        IconDemo app = new IconDemo();
        app.run();
    }

    /**
     *Méthode d'affichage d'une icône dans la barre d'état système
     */
    private void run() {
        Image image = Toolkit.getDefaultToolkit().createImage( ClassLoader.getSystemResource("icon.png ") ); //Préparer l'image de l'icône
        TrayIcon icon = new TrayIcon(image, "Sample Java App"); //* 1 Généré sous forme d'icône de barre d'état
        icon.setImageAutoSize(true); //redimensionner
        
        try {
			SystemTray.getSystemTray().add(icon); //* 2 Ajouté à la barre d'état système
		} catch (AWTException e) {
			e.printStackTrace();
		}
    }
}

Résultat d'exécution

実行結果

Il a été ajouté comme ça. Cependant, sur Mac, l'icône Java était également affichée dans le Dock. Si vous n'en avez pas l'intention, il semble que vous puissiez l'éviter en ajoutant l'option suivante en tant qu'argument VM lors du démarrage du programme.


-Dapple.awt.UIElement=true

En d'autres termes, si vous utilisez Java brut, démarrez-le comme suit.


java -Dapple.awt.UIElement=true IconDemo

Passez également le curseur de la souris sur l'icône.

ツールチップ

Vous voyez «Exemple d'application Java». Cela s'appelle une puce d'outil, et le code ci-dessus vous demande d'afficher la chaîne de caractères spécifiée.

※1 TrayIcon

La classe TrayIcon représente une icône qui peut être ajoutée à la barre d'état système. Le code ci-dessus prend deux arguments, mais vous pouvez en prendre jusqu'à trois.


/*
1er argument:image Image d'icône (obligatoire)
2ème argument:Chaîne de caractères affichée lorsque le curseur de la souris est placé sur l'icône d'info-bulle (facultatif)
3e argument:Menu contextuel (facultatif) Utilisé dans l'étape suivante
*/
TrayIcon icon = new TrayIcon(Image image, String tooltip, PopupMenu popup);

※2 SystemTray

La classe SystemTray représente la barre d'état système pour chaque OS. Utilisez SystemTray.getSystemTray () pour obtenir la barre d'état système réelle, et utilisez la méthode ʻadd () `pour y ajouter une icône de barre d'état.

Vous pouvez également utiliser la méthode SystemTray.isSupported (), comme le code ci-dessous, pour voir si java peut manipuler la barre d'état système dans l'environnement d'exécution en premier lieu.

IconDemo.java



import java.awt.SystemTray;

public class IconDemo {

    public static void main(String[] args) {
        IconDemo app = new IconDemo();
        app.check();
    }
    
    /**
    *Vérifiez si l'environnement d'exécution prend en charge la barre d'état système
    */
    private void check() {
        Boolean check = SystemTray.isSupported();
        System.out.println("Support status: " + check);
    }

}

Cependant, il semble que ** la barre d'état système n'est pas nécessairement indisponible ** si cela devient «faux». La source est moi-même. Quand j'ai essayé de faire la même chose avec Spring Boot, j'ai obtenu une exception Headless comme décrit ci-dessous, et la méthode ʻisSupported () est devenue false`. Cependant, en prenant l'action corrective décrite plus loin, il était possible de l'afficher même s'il reste «faux».

Lorsqu'une exception HeadlessException se produit

Dans mon cas, cela s'est produit lorsque j'utilisais Spring Boot. La cause en est que le mode sans tête d'AWT est activé et, lorsqu'il est activé, les fonctions liées à AWT sont rarement disponibles.

Il peut être désactivé en spécifiant ce qui suit dans l'argument VM.

-Djava.awt.headless=false

En d'autres termes, si vous utilisez Java brut, démarrez-le comme suit.


java -Djava.awt.headless=false IconDemo

Si vous utilisez Spring Boot, vous pouvez également le désactiver en modifiant la méthode main () comme suit.


/*****Avant de changer*****/
public static void main(String[] args) {
	SpringApplication.run(IconDemo.class, args);
}

/*****Après avoir changé*****/
public static void main(String[] args) {
	SpringApplicationBuilder builder = new SpringApplicationBuilder(IconDemo.class);
	builder.headless(false).run(args);		
}

(Cependant, je ne comprends pas les effets néfastes de la désactivation de ce qui était initialement activé dans Spring Boot, etc.)

ÉTAPE 2: afficher le menu

Crée un menu qui apparaît lorsque vous cliquez avec le bouton droit sur une icône sous Windows et lorsque vous cliquez sur l'icône sur Mac. Il décrit également ce qui se passe lorsque vous cliquez sur chaque menu. De plus, le style d'écriture est légèrement différent de STEP1.

code

IconDemo.java



import java.awt.AWTException;
import java.awt.Image;
import java.awt.MenuItem;
import java.awt.PopupMenu;
import java.awt.SystemTray;
import java.awt.Toolkit;
import java.awt.TrayIcon;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class IconDemo {

    public static void main(String[] args) {
        IconDemo app = new IconDemo();
        app.run();
    }

    /**
     *Méthode d'affichage d'une icône dans la barre d'état système
     */
    private void run() {
        SystemTray tray = SystemTray.getSystemTray(); //Obtenir la barre d'état système
        PopupMenu popup = new PopupMenu(); //* 4 Générer un menu contextuel
        Image image = Toolkit.getDefaultToolkit().createImage( ClassLoader.getSystemResource("icon.png ") ); //Préparer l'image de l'icône
        TrayIcon icon = new TrayIcon(image, "Sample Java App", popup); //* 4 Généré sous forme d'icône de plateau
        icon.setImageAutoSize(true); //redimensionner

        //* 3 Créez le contenu du menu contextuel
        MenuItem item1 = new MenuItem("Hello");
        item1.addActionListener(new ActionListener(){
            @Override
            public void actionPerformed(ActionEvent e) {
                System.out.println("Hello world!!");
            }
        });

        MenuItem item2 = new MenuItem("Exit");
        item2.addActionListener(new ActionListener(){
            @Override
            public void actionPerformed(ActionEvent e) {
                tray.remove(icon);
                // System.exit(0);
            }
        });
        popup.add(item1); // ※4
        popup.add(item2); // ※4
        
        try {
            tray.add(icon); //Ajouter à la barre d'état système
		} catch (AWTException e) {
			e.printStackTrace();
		}
    }
}

Résultat d'exécution

Cliquez avec le bouton droit sur l'icône pour Windows et cliquez dessus pour Mac.

実行結果

Cliquez sur "Hello" pour afficher "Hello world !!" sur la console, et cliquez sur "Exit" pour quitter le programme.

※3 MenuItem

Chaque élément du menu contextuel est créé avec la classe MenuItem. Dans l'argument du constructeur, spécifiez la chaîne de caractères du nom d'affichage dans le menu.

De plus, le traitement après avoir cliqué sur le menu est ajouté en utilisant la méthode ʻaddActionListener () . Ce style d'écriture est-il familier à quiconque a créé des applications GUI? L'argument de la méthode ʻaddActionListener () est une instance qui implémente l'interface ʻActionListener. Le code ci-dessus l'implémente en utilisant une classe anonyme. L'interface ʻActionListener doit toujours remplacer la méthode ʻactionPerformed (ActionEvent e) `, dans laquelle vous écrivez ce qui se passe après avoir cliqué sur le menu.

Dans le menu "Quitter", le processus pour terminer le programme est écrit. Vous pouvez utiliser System.exit (0); pour le forcer à quitter, mais cela ne semble pas être une bonne idée de trop l'utiliser. En parlant de ce programme, il suffit d'écrire tray.remove (icône); et de supprimer l'icône de la barre d'état de la barre d'état système quittera le programme.

※4 PopupMenu

La classe PopupMenu représente un seul menu contextuel. En spécifiant ce PopupMenu dans le 3ème argument lors de la génération de TrayIcon, vous pouvez afficher le menu lorsque vous cliquez avec le bouton droit ou cliquez sur l'icône.

Le MenuItem créé précédemment peut être ajouté en utilisant la méthode ʻadd ()` de ce PopupMenu.

ÉTAPE 3: afficher un message (notification)

Dans le code STEP2 ci-dessus, quand j'ai cliqué sur le menu "Hello", "Hello world !!" était affiché sur la console, mais affichons quelque chose sous forme de message dans la barre d'état système au lieu de la console.

code

Modifiez le contenu de la méthode ʻactionPerformed () de ʻitem1 dans STEP2 comme suit.


import java.awt.TrayIcon.MessageType; //Ajouter pour importer

/**
*Avant de changer
*/
@Override
public void actionPerformed(ActionEvent e) {
    System.out.println("Hello world!!");
}

/**
*Après avoir changé
*/
@Override
public void actionPerformed(ActionEvent e) {
    // ※5
    icon.displayMessage("Exemple de programme", "Bonjour le monde! Ceci est un exemple de message.", MessageType.INFO);
}

Résultat d'exécution

Essayez de cliquer sur le menu "Bonjour".

実行結果

Malheureusement, il n'est pas apparu sur Mac. Dans le cas de Mac, il semble que le message soit affiché à l'aide du centre de notification de Mac, mais il semble qu'il n'y ait aucun moyen de l'utiliser directement depuis Java. La personne qui a répondu ici a présenté la solution, mais cela n'a pas encore été fait. C'est une vérification.

Résumé

J'ai l'impression que ce n'est pas une manière très moderne.

Si vous connaissez un meilleur moyen, j'apprécierais que vous me le disiez.

La page que j'ai utilisée comme référence

Recommended Posts

Affichage de l'icône dans la barre d'état système en Java (Windows: zone de notification / Mac: barre de menus)
Appelez l'API de notification Windows en Java
Changer le codage Java dans Windows