Rendre les gadgets de calendrier créés avec JavaFX compatibles avec Java SE 9

Rendre les gadgets de calendrier créés avec JavaFX compatibles avec Java SE 9

J'ai commencé à écrire cet article lorsque j'ai essayé de le publier sur JavaFX Advent Calendar 2017, mais je n'ai pas pu prendre le temps à cause du travail et de la grippe, donc j'ai plus tard C'est ouvert au public.

introduction

Dans le coin du bureau se trouve un gadget de bureau qui affiche de petites fonctionnalités GUI telles que des horloges et des calendriers. Dans l'ancien temps, c'était un gadget de Windows Vista / 7, tel que xclock et oclock de X Window System. Cependant, les gadgets Windows sont obsolètes depuis Windows 8 en raison de vulnérabilités.

Par conséquent, sous Windows 8 ou version ultérieure (10, etc.), si vous voulez un gadget de bureau, vous devrez rechercher un tel programme séparément, l'obtenir et l'utiliser. Il existe un certain nombre de logiciels gratuits qui ressemblent à des gadgets de bureau, mais j'ai pensé que ce serait bien pour les programmeurs d'essayer d'utiliser leurs propres gadgets, alors j'ai fait un peu avec JavaFX. Ce domaine a été présenté lors de la prochaine session du JJUG CCC 2017 Spring.

En tant que gadget de bureau, je voulais une horloge et un calendrier, j'ai donc créé un gadget de calendrier en suivant le gadget de l'horloge.

Cette fois, le contenu est de rendre le gadget de calendrier créé avec Java SE 8 compatible avec Java SE 9.

Gadget de calendrier

Le gadget de calendrier utilise le contrôle DatePicker de JavaFX pour afficher un petit calendrier (mois) dans un coin du bureau.

image.png

Le référentiel du programme (code source) est le suivant (Github). CalendarGadget

Ce programme est écrit en Java SE 8. J'ai écrit le moyen de créer un gadget de calendrier avec Java SE 8 dans le blog suivant.

Éléments compatibles Java SE 9 pour les gadgets de calendrier

Nous rendrons ce gadget de calendrier compatible avec Java SE 9, et à ce moment-là, nous ferons ce qui suit.

  1. Prise en charge des modifications de package de la classe DatePickerSkin
  2. Prend en charge le système de modules Java SE 9 (JPMS)
  3. Correspondance avec le jour en cours au retour de veille / veille prolongée

La politique correspondante est brièvement décrite ci-dessous. Après cela, décrivez les détails de correspondance de chaque article.

Prise en charge des modifications de package de la classe DatePickerSkin

La partie d'affichage du calendrier du contrôle DatePicker utilise la classe DatePickerSkin, qui a un nom de package lors du passage de Java SE 8 à Java SE 9.

De

Il a été changé en. Il est passé d'une API interne à une API publique. Cependant, vous devez modifier le code source de Java SE 8 et 9.

Compatible avec Java SE 9 Module System (JPMS)

À partir de Java SE 9, en plus de la méthode conventionnelle de référencement des fichiers de classe et des fichiers JAR au moment de l'exécution, une méthode de référencement des fichiers de module au moment de l'exécution a été ajoutée.

Ici, comme c'est un gros problème, nous correspondrons au module.

Correspondance lors du retour de veille / veille prolongée

Le gadget de calendrier marque la date du jour afin que vous puissiez voir la date du jour (un rectangle entoure le jour du jour). Par conséquent, si la date change pendant que vous exécutez le gadget de calendrier, vous devrez modifier les marquages de la date du jour au jour suivant. Lors de la création avec Java SE 8, l'heure jusqu'à la fin de la journée est calculée lorsque le gadget de calendrier est démarré et le processus de mise à jour de la date du jour est exécuté une fois ce délai écoulé (implémenté à l'aide de ScheduledExecutorService). ..

Cependant, si le PC exécutant le gadget se met en veille ou en veille prolongée au milieu, ce processus ne sera pas activé au moment souhaité. Par conséquent, j'essaie de vérifier le processus de mise à jour de la date toutes les heures comme une mesure minutieuse.

À partir de Java SE 9, la possibilité de savoir par événement qu'un PC est entré en veille ou en veille prolongée et a été restauré à partir du mode veille ou hibernation a été ajoutée.

Par conséquent, je profiterai de cet événement.

Implémentation de DatePickerSkin pour Java SE 9

Renommez le package DatePickerSkin, qui est le premier élément de prise en charge de Java SE 9.

CalendarGadgetApp.java


- import com.sun.javafx.scene.control.skin.DatePickerSkin;
+ import javafx.scene.control.skin.DatePickerSkin;

Configuration du système de module Java

Prend en charge le système de modules Java, qui est le deuxième élément de prise en charge de Java SE 9. Cette fois, je décrirai principalement la correspondance avec NetBeans.

Utiliser le développement NetBeans IDE 9

NetBeans 9 pour Java SE 9 (JDK 9) n'est pas encore officiellement publié pour le moment. Par conséquent, nous utiliserons la version de développement de NetBeans 9. http://bits.netbeans.org/download/trunk/nightly/latest/

Dans NetBeans 9, le type de projet correspondant au système de modules est Java Modular Project. Les types de projet tels que les applications JavaFX ne sont pas compatibles avec les systèmes de modules. Par conséquent, je vais recréer le projet une fois.

Créer un nouveau projet

Créez un répertoire de travail vide et créez deux nouveaux projets en dessous.

  1. Créez un nom de projet [GadgetSupport] sous un répertoire de travail vide dans le menu [Fichier]> [Nouveau projet]> [Java]> [Projet modulaire Java].
  2. Sélectionnez le menu [Fichier]> [Nouveau projet]> [Java]> [Projet modulaire Java] et créez un nom de projet [Gadget de calendrier] sous un répertoire de travail vide.

Voici la première étape de l'écran de l'assistant Nouveau projet. [Java Modular Project] a été ajouté à la catégorie [Java].

image.png

La prochaine étape est la suivante sur l'écran de l'assistant Nouveau projet. Spécifiez l'emplacement et le nom du projet pour créer le projet.

image.png

Le projet modulaire Java peut contenir plusieurs modules sous un même projet. Au départ, le module est vide. Cette fois, nous n'inclurons qu'un seul module dans chacun des deux projets que nous avons créés.

Définissez un module dans chaque projet.

  1. Cliquez avec le bouton droit sur le projet GadgetSupport, sélectionnez Nouveau> Module et entrez com.torutk.gadget.support comme nom de module.
  2. Cliquez avec le bouton droit de la souris sur le projet CalendarGadget, sélectionnez Nouveau> Module et entrez com.torutk.gadget.calendar comme nom de module.

L'étape suivante consiste à sélectionner un projet et à ajouter un module.

image.png

Sur l'écran Nouveau module, entrez le nom du module.

image.png

Le nom du module est le nom de package le plus important des packages à publier (d'après la convention de dénomination de Java Language Specification 6.1).

Lorsque vous créez un module, module-info.java est généré.

image.png

Contrairement à la configuration précédente du projet NetBeans, un dossier de modules est créé sous le projet, un dossier de classes est créé sous celui-ci et le package du fichier source est placé ici. Comme module-info.java est fourni au niveau supérieur (pas de nom de package), il est placé dans ce que NetBeans décrit comme le <package par défaut>.

La structure des fichiers de répertoire est la suivante.

image.png

Apportez le fichier source ici. Lorsque j'apporte le fichier source, l'instruction d'importation est entièrement erronée.

image.png

Ajout de la définition du module (GadgetSupport)

Nous décrirons la définition du module du module com.torutk.gadget.support du projet GadgetSupport.

Dans le système de modules Java SE 9, si vous utilisez une classe autre que celle qui appartient au module java.base, vous devez décrire explicitement le module qui contient la classe à utiliser dans le fichier de définition de module (module-info.java).

Un message d'erreur apparaît lorsque vous placez le curseur sur la marque (: exclamation :) au début de la ligne d'erreur. L'écran suivant affiche une erreur dans java.util.prefs.Preferences.

image.png

Ajoutez le module java.prefs à module-info.java en fonction du message d'erreur.

module-info.java


module com.torutk.gadget.support {
    requires java.prefs;
}

De même, ajoutez la description d'utilisation du module correspondant à l'erreur de l'instruction d'importation restante.

image.png

Le message d'erreur nous indique que nous avons besoin de deux modules, javafx.graphics et javafx.controls. Vous pouvez décrire ces deux modules dans module-info.java, mais comme javafx.graphics et javafx.controls ont une dépendance transitoire, spécifiez uniquement javafx.controls dans la définition du module du côté application. Sera résolu.

module-info.java


module com.torutk.gadget.support {
    requires java.prefs;
    requires javafx.controls;
}

La définition du module de javafx.controls a la description suivante.

    requires transitive javafx.base;
    requires transitive javafx.graphics;

Puisque transitive est spécifié, deux modules, javafx.base et javafx.graphics, sont automatiquement disponibles pour les modules qui utilisent javafx.controls.

Ensuite, puisque le projet GadgetSupport est une bibliothèque utilitaire, vous devez publier le package com.torutk.gadget.support dans votre application (telle que CalendarGadget).

module-info.java


module com.torutk.gadget.support {
    requires java.prefs;
    requires javafx.controls;
    exports com.torutk.gadget.support;
}

Cela va construire. Les fichiers de classe compilés sont générés sous build / modules et les fichiers JAR sont générés sous dist.

GadgetSupport
  +-- build
  |     +-- modules
  |           +-- com.torutk.gadget.support
  |                 +-- module-info.class
  |                 +-- com
  |                       +-- torutk
  |                             +-- gadget
  |                                   +-- support
  |                                         +-- TinyGadgetSupport.class
  +-- dist
  :     +-- com.torutk.gadget.support.jar

Ajout de la définition du module (CalendarGadget)

Nous décrirons la définition du module du module com.torutk.gadget.calendar du projet Calendar Gadget.

Cette fois, en plus de l'API standard Java SE 9, nous utiliserons la bibliothèque (GadgetSupport) que nous avons créée, alors ajoutez la dépendance de bibliothèque dans les paramètres du projet. GadgetSupport a été créé en tant que module, alors définissez-le en ajoutant un module.

Cliquez avec le bouton droit sur le projet CalendarGadget et sélectionnez Propriétés. Sélectionnez Bibliothèques dans le volet gauche, cliquez sur l'onglet Compiler dans le volet droit, cliquez sur le + à l'extrême droite de Modulepath et sélectionnez Ajouter un projet ...

image.png

L'écran Ajouter un projet s'ouvre, sélectionnez le projet Gadget Support. Ensuite, le fichier JAR généré par le projet sera affiché.

image.png

Décrivez les modules dépendants dans le fichier de définition de module.

module-info.java


module com.torutk.gadget.calendar {
    requires java.logging;
    requires java.prefs;
    requires javafx.controls;
    requires com.torutk.gadget.support;
}

J'ai eu une erreur de compilation, alors je vais l'essayer. Ensuite, j'obtiens l'erreur suivante:

run:
Exception in Application constructor
Exception in thread "main" java.lang.reflect.InvocationTargetException
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:564)
	at java.base/sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:945)
Caused by: java.lang.RuntimeException: Unable to construct Application instance: class com.torutk.gadget.calendar.CalendarGadgetApp
	at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:963)
	at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication$2(LauncherImpl.java:198)
	at java.base/java.lang.Thread.run(Thread.java:844)
Caused by: java.lang.IllegalAccessException: class com.sun.javafx.application.LauncherImpl (in module javafx.graphics) cannot access class com.torutk.gadget.calendar.CalendarGadgetApp (in module com.torutk.gadget.calendar) because module com.torutk.gadget.calendar does not export com.torutk.gadget.calendar to module javafx.graphics
	at java.base/jdk.internal.reflect.Reflection.newIllegalAccessException(Reflection.java:361)
	at java.base/java.lang.reflect.AccessibleObject.checkAccess(AccessibleObject.java:589)
	at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:479)
	at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$8(LauncherImpl.java:875)
	at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runAndWait$11(PlatformImpl.java:449)
	at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$9(PlatformImpl.java:418)
	at java.base/java.security.AccessController.doPrivileged(Native Method)
	at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:417)
	at javafx.graphics/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96)
	at javafx.graphics/com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
	at javafx.graphics/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:175)
	... 1 more

Voici les messages qui sont la principale source de l'erreur:

com.sun.javafx.application.LauncherImpl (in module javafx.graphics) cannot access 
class com.torutk.gadget.calendar.CalendarGadgetApp (in module 
com.torutk.gadget.calendar) because module com.torutk.gadget.calendar does not export 
com.torutk.gadget.calendar to module javafx.graphics

Il indique que la classe d'application JavaFX CalendarGadgetApp doit être accessible à partir du module javafx.graphics.

Vous pouvez l'exécuter en ajoutant l'instruction suivante au fichier de définition de module.

opens com.torutk.gadget.calendar;

Cette fois, il peut être exécuté avec des exportations au lieu d'ouvertures, mais lors de l'utilisation de FXML ou de la liaison à l'avenir, un accès de réflexion sera requis du module javafx à la classe côté application, il est donc nécessaire d'utiliser des ouvertures au lieu des exportations. .. Par conséquent, dans la définition du module de l'application JavaFX, spécifiez-le avec opens.

Prend en charge la date actuelle lors du retour du mode veille / veille prolongée

C'est le dernier des trois éléments.

Premièrement, il reçoit le retour de veille / hibernation du système d'exploitation sous forme d'événement.

   private void initResumeProc() {
        Desktop desktop = Desktop.getDesktop();
        desktop.addAppEventListener(new SystemSleepListener() {
            @Override
            public void systemAboutToSleep(SystemSleepEvent e) {
                logger.info("Detect system about to sleep.");
            }

            @Override
            public void systemAwoke(SystemSleepEvent e) {
                logger.info("Detect system awake.");
                if (schedule != null ) {
                    schedule.cancel(true);
                }
                crossoverDate();
            }
        });
    }

Transmettez une instance de la classe d'implémentation de l'interface SystemSleepListener à la méthode addAppEventListener ajoutée de Java SE 9 à la classe java.awt.Desktop. Ensuite, lorsque le système d'exploitation se met en veille ou en veille prolongée (suspension), et lorsqu'il se réveille, la méthode correspondante de SystemSleepListener est appelée. Cette fois, définissez à nouveau le processus de mise à jour de la date (méthode crossoverDate) à ce moment. Si la planification du processus de mise à jour de la date a déjà été définie, annulez la planification.

Dépôt

Le référentiel Calendar Gadget avec prise en charge de Java SE 9 est le suivant.

https://github.com/torutk/CalendarGadget/tree/jdk9_module

Recommended Posts

Rendre les gadgets de calendrier créés avec JavaFX compatibles avec Java SE 9
Rendre l'environnement SpringBoot1.5 + Gradle4.4 + Java8 + Docker compatible avec Java11
Outil GUI refactorisé réalisé avec Java8 + JavaFX en 2016
[Rails] Rendre la pagination compatible avec Ajax
Créer un outil de diaporama avec JavaFX
Exécuter des applications écrites en Java8 en Java6
Comment créer un résumé de calendrier Java
Créez quelque chose comme Enum de Java avec Typescript
Obtenez un cryptage compatible OpenSSL avec Java / PHP
Distributeur automatique fabriqué avec Java (piloté par domaine)
[Java] Rendez le programme 10 fois plus rapide avec parallelStream
J'ai essayé de faire une authentification de base avec Java
Course d'obstacles facile avec traitement pour Java
Les étudiants ont défié Java SE 7/8 Bronze sans aucune diligence.
Couverture de code Java plus confortable avec Jacoco 0.8.0
Rendre la ligne Java Stream agréable avec Eclipse
Kit de développement Java SE 8u161 - configuration avec alternatives
Facile à créer LINE BOT avec Java Servlet