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 ...)
Cette fois, je vais l'essayer avec deux OS.
OS: Windows 10 Pro / macOS High Sierra
Java: 1.8
Sauf indication contraire, nous n'utiliserons rien de spécialisé pour Spring Boot.
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.
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();
}
}
}
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».
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.)
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.
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();
}
}
}
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.
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.
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);
}
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.
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.