Machen Sie mit JavaFX erstellte Kalender-Gadgets mit Java SE 9 kompatibel

Machen Sie mit JavaFX erstellte Kalender-Gadgets mit Java SE 9 kompatibel

Ich habe angefangen, diesen Artikel zu schreiben, als ich versuchte, ihn auf JavaFX Adventskalender 2017 zu veröffentlichen, aber ich konnte mir aufgrund von Arbeit und Influenza keine Zeit nehmen, also später Es ist für die Öffentlichkeit zugänglich.

Einführung

In der Ecke des Desktops befindet sich ein Desktop-Gadget, das kleine GUI-Funktionen wie Uhren und Kalender anzeigt. Früher war es ein Gadget von Windows Vista / 7, wie z. B. xclock und oclock von X Window System. Windows-Gadgets sind jedoch seit Windows 8 aufgrund von Sicherheitslücken veraltet.

Wenn Sie in Windows 8 oder höher (10 usw.) ein Desktop-Gadget möchten, müssen Sie daher separat nach einem solchen Programm suchen, es abrufen und verwenden. Es gibt viele kostenlose Software, die wie Desktop-Gadgets aussieht, aber ich dachte, es wäre gut für Programmierer, ihre eigenen Gadgets zu verwenden, also habe ich ein wenig mit JavaFX gemacht. Dieser Bereich wurde in der nächsten Sitzung auf der JJUG CCC 2017 Spring vorgestellt.

Als Desktop-Gadget wollte ich eine Uhr und einen Kalender, also habe ich ein Kalender-Gadget erstellt, das dem Uhr-Gadget folgt.

Dieses Mal besteht der Inhalt darin, das mit Java SE 8 erstellte Kalender-Gadget mit Java SE 9 kompatibel zu machen.

Kalender-Gadget

Das Kalender-Gadget verwendet das DatePicker-Steuerelement von JavaFX, um einen kleinen Kalender (Monat) in einer Ecke des Desktops anzuzeigen.

image.png

Das Programm-Repository (Quellcode) lautet wie folgt (Github). CalendarGadget

Dieses Programm ist in Java SE 8 geschrieben. Ich habe im folgenden Blog geschrieben, wie man mit Java SE 8 ein Kalender-Gadget erstellt.

  1. Unterstützung für Paketänderungen der DatePickerSkin-Klasse
  2. Unterstützt das Java SE 9-Modulsystem (JPMS)
  3. Korrespondenz zum aktuellen Tag bei Rückkehr aus dem Schlaf / Winterschlaf

Die entsprechende Richtlinie wird nachstehend kurz beschrieben. Beschreiben Sie anschließend die Korrespondenzdetails der einzelnen Artikel.

Unterstützung für Paketänderungen der DatePickerSkin-Klasse

Der Kalenderanzeigeteil des DatePicker-Steuerelements verwendet die DatePickerSkin-Klasse, die beim Wechsel von Java SE 8 zu Java SE 9 einen Paketnamen hat.

Von

Es wurde geändert in. Es wurde von einer internen API auf eine öffentliche API aktualisiert. Sie müssen jedoch den Quellcode für Java SE 8 und 9 ändern.

Kompatibel mit Java SE 9 Module System (JPMS)

Ab Java SE 9 wurde zusätzlich zu der herkömmlichen Methode zum Referenzieren von Klassendateien und JAR-Dateien zur Laufzeit eine Methode zum Referenzieren von Moduldateien zur Laufzeit mit dem Modulpfad hinzugefügt.

Da es sich um eine große Sache handelt, werden wir hier dem Modul entsprechen.

Korrespondenz bei Rückkehr aus dem Schlaf / Winterschlaf

Das Kalender-Gadget markiert das heutige Datum, sodass Sie das aktuelle Datum sehen können (ein Rechteck umgibt den heutigen Tag). Wenn sich das Datum ändert, während Sie das Kalender-Gadget ausführen, müssen Sie daher die Markierungen am heutigen Datum auf den nächsten Tag ändern. Beim Erstellen mit Java SE 8 wird die Zeit bis zum Ende des Tages berechnet, wenn das Kalender-Gadget gestartet wird, und der Vorgang zum Aktualisieren des heutigen Datums wird nach Ablauf dieser Zeit ausgeführt (implementiert mit ScheduledExecutorService). ..

Wenn jedoch der PC, auf dem das Gadget ausgeführt wird, in den Ruhezustand oder in den Ruhezustand wechselt, wird dieser Vorgang nicht zum gewünschten Zeitpunkt aktiviert. Daher versuche ich, den Prozess der Datumsaktualisierung stündlich als sorgfältige Maßnahme zu überprüfen.

Ab Java SE 9 wurde die Möglichkeit hinzugefügt, anhand eines Ereignisses zu erkennen, dass ein PC in den Ruhezustand oder Ruhezustand eingetreten ist und aus dem Ruhezustand oder Ruhezustand wiederhergestellt wurde.

Daher werde ich diese Veranstaltung nutzen.

Implementierung von DatePickerSkin für Java SE 9

Benennen Sie das DatePickerSkin-Paket um, das das erste Java SE 9-Supportelement ist.

CalendarGadgetApp.java


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

Einstellung für Java-Modulsystem

Unterstützt das Java-Modulsystem, das das zweite Java SE 9-Unterstützungselement ist. Dieses Mal werde ich hauptsächlich die Korrespondenz mit NetBeans beschreiben.

Verwenden Sie die NetBeans IDE 9-Entwicklung

NetBeans 9 für Java SE 9 (JDK 9) wurde zu diesem Zeitpunkt noch nicht offiziell veröffentlicht. Daher werden wir die Entwicklungsversion von NetBeans 9 verwenden. http://bits.netbeans.org/download/trunk/nightly/latest/

In NetBeans 9 ist der dem Modulsystem entsprechende Projekttyp Java Modular Project. Projekttypen wie JavaFX-Anwendungen sind nicht mit Modulsystemen kompatibel. Daher werde ich das Projekt einmal neu erstellen.

Erstellen Sie ein neues Projekt

Erstellen Sie ein leeres Arbeitsverzeichnis und erstellen Sie zwei neue Projekte darunter.

  1. Erstellen Sie einen Projektnamen [GadgetSupport] unter einem leeren Arbeitsverzeichnis im Menü [Datei]> [Neues Projekt]> [Java]> [Java Modular Project].
  2. Wählen Sie das Menü [Datei]> [Neues Projekt]> [Java]> [Java Modular Project] und erstellen Sie einen Projektnamen [Kalender-Gadget] in einem leeren Arbeitsverzeichnis.

Das Folgende ist der erste Schritt auf dem Bildschirm des Assistenten für neue Projekte. [Java Modular Project] wurde der Kategorie [Java] hinzugefügt.

image.png

Weiter ist der nächste Schritt auf dem Bildschirm des Assistenten für neue Projekte. Geben Sie den Speicherort und den Projektnamen an, um das Projekt zu erstellen.

image.png

Das Java Modular Project kann mehrere Module unter einem Projekt enthalten. Das Modul ist zunächst leer. Dieses Mal werden wir nur ein Modul in jedes der beiden von uns erstellten Projekte aufnehmen.

Definieren Sie in jedem Projekt ein Modul.

  1. Klicken Sie mit der rechten Maustaste auf das GadgetSupport-Projekt, wählen Sie Neu> Modul und geben Sie com.torutk.gadget.support als Modulnamen ein.
  2. Klicken Sie mit der rechten Maustaste auf das CalendarGadget-Projekt, wählen Sie Neu> Modul und geben Sie com.torutk.gadget.calendar als Modulnamen ein.

Der nächste Schritt besteht darin, ein Projekt auszuwählen und ein Modul hinzuzufügen.

image.png

Geben Sie im Bildschirm Neues Modul den Modulnamen ein.

image.png

Der Modulname ist der wichtigste Paketname der zu veröffentlichenden Pakete (gemäß der Namenskonvention von Java Language Specification 6.1).

Wenn Sie ein Modul erstellen, wird module-info.java generiert.

image.png

Im Gegensatz zu herkömmlichen NetBeans-Projektkonfigurationen wird unter dem Projekt ein Modulordner erstellt, darunter ein Klassenordner und hier das Quelldateipaket. Da module-info.java auf der obersten Ebene bereitgestellt wird (kein Paketname), wird es in das eingefügt, was NetBeans als beschreibt.

Die Verzeichnisdateistruktur ist wie folgt.

image.png

Bringen Sie die Quelldatei hierher. Wenn ich die Quelldatei einbringe, ist die Importanweisung fehlerhaft.

image.png

Hinzufügen einer Moduldefinition (GadgetSupport)

Wir werden die Moduldefinition des Moduls com.torutk.gadget.support des GadgetSupport-Projekts beschreiben.

Wenn Sie im Java SE 9-Modulsystem eine andere Klasse als die zum Modul java.base gehörende verwenden, müssen Sie das Modul, das die Klasse enthält, die in der Moduldefinitionsdatei (module-info.java) verwendet werden soll, explizit beschreiben.

Eine Fehlermeldung wird angezeigt, wenn Sie den Cursor auf die Markierung (: Ausrufezeichen :) am Anfang der Fehlerzeile setzen. Der folgende Bildschirm zeigt einen Fehler in java.util.prefs.Preferences an.

image.png

Fügen Sie das Modul java.prefs gemäß der Fehlermeldung zu module-info.java hinzu.

module-info.java


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

Fügen Sie in ähnlicher Weise die Modulverwendungsbeschreibung hinzu, die dem Fehler der verbleibenden Importanweisung entspricht.

image.png

Die Fehlermeldung sagt uns, dass wir zwei Module benötigen, javafx.graphics und javafx.controls. Sie können diese beiden Module in module-info.java beschreiben. Da jedoch javafx.graphics und javafx.controls eine Übergangsabhängigkeit aufweisen, geben Sie in der Moduldefinition auf der Anwendungsseite nur javafx.controls an. Wird geklärt werden.

module-info.java


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

Die Moduldefinition von javafx.controls enthält die folgende Beschreibung.

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

Da transitiv angegeben ist, sind zwei Module, javafx.base und javafx.graphics, automatisch für Module verfügbar, die javafx.controls verwenden.

Da das GadgetSupport-Projekt eine Dienstprogrammbibliothek ist, müssen Sie das Paket com.torutk.gadget.support in Ihrer Anwendung (z. B. CalendarGadget) veröffentlichen.

module-info.java


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

Dies wird bauen. Kompilierte Klassendateien werden unter build / modules und JAR-Dateien unter dist generiert.

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

Hinzufügen einer Moduldefinition (CalendarGadget)

Wir werden die Moduldefinition des Moduls com.torutk.gadget.calendar des Calendar Gadget-Projekts beschreiben.

Dieses Mal verwende ich zusätzlich zur Java SE 9-Standard-API eine von mir erstellte Bibliothek (GadgetSupport). Fügen Sie daher in den Projekteinstellungen eine Bibliotheksabhängigkeit hinzu. GadgetSupport wurde als Modul erstellt. Legen Sie es also fest, indem Sie ein Modul hinzufügen.

Klicken Sie mit der rechten Maustaste auf das CalendarGadget-Projekt und wählen Sie Eigenschaften. Wählen Sie im linken Bereich Bibliotheken aus, klicken Sie im rechten Bereich auf die Registerkarte Kompilieren, klicken Sie auf das + ganz rechts in Modulepath und wählen Sie Projekt hinzufügen ...

image.png

Der Bildschirm Projekt hinzufügen wird geöffnet. Wählen Sie das Gadget-Support-Projekt aus. Anschließend wird die vom Projekt generierte JAR-Datei angezeigt.

image.png

Beschreiben Sie die abhängigen Module in der Moduldefinitionsdatei.

module-info.java


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

Ich habe einen Kompilierungsfehler, also werde ich es versuchen. Dann bekomme ich folgenden Fehler:

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

Hier sind die Meldungen, die die Hauptursache für den Fehler sind:

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

Es besagt, dass auf die JavaFX-Anwendungsklasse CalendarGadgetApp über das Modul javafx.graphics zugegriffen werden muss.

Sie können es ausführen, indem Sie der Moduldefinitionsdatei die folgende Anweisung hinzufügen.

opens com.torutk.gadget.calendar;

Dieses Mal kann es mit Exporten anstelle von Öffnen ausgeführt werden. Wenn Sie jedoch in Zukunft FXML verwenden oder binden, ist ein Reflexionszugriff vom Javafx-Modul auf die Klasse auf der Anwendungsseite erforderlich. Daher muss Öffnen anstelle von Exporten verwendet werden. .. Geben Sie sich daher in der Moduldefinition der JavaFX-Anwendung mit opens an.

Unterstützt das aktuelle Datum bei der Rückkehr aus dem Ruhezustand

Dies ist der letzte der drei Punkte.

Erstens erhält es die Rückkehr aus dem Ruhezustand / Ruhezustand des Betriebssystems als Ereignis.

   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();
            }
        });
    }

Übergeben Sie eine Instanz der Implementierungsklasse der SystemSleepListener-Schnittstelle an die addAppEventListener-Methode, die von Java SE 9 zur java.awt.Desktop-Klasse hinzugefügt wurde. Wenn das Betriebssystem in den Ruhezustand versetzt oder in den Ruhezustand versetzt (angehalten) wird und wenn es aufwacht, wird die entsprechende Methode von SystemSleepListener aufgerufen. Stellen Sie diesmal den Datumsaktualisierungsprozess (crossoverDate-Methode) zu diesem Zeitpunkt erneut ein. Wenn der Zeitplan für die Aktualisierung des Datums bereits festgelegt wurde, brechen Sie den Zeitplan ab.

Repository

Das Kalender-Gadget-Repository mit Java SE 9-Unterstützung lautet wie folgt.

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

Recommended Posts

Machen Sie mit JavaFX erstellte Kalender-Gadgets mit Java SE 9 kompatibel
Machen Sie die SpringBoot1.5 + Gradle4.4 + Java8 + Docker-Umgebung mit Java11 kompatibel
Überarbeitetes GUI-Tool, das 2016 mit Java8 + JavaFX erstellt wurde
[Rails] Pagenation mit Ajax kompatibel machen
Erstellen Sie mit JavaFX ein Diashow-Tool
Führen Sie in Java8 geschriebene Anwendungen in Java6 aus
So erstellen Sie eine Java-Kalenderzusammenfassung
Machen Sie so etwas wie Javas Enum mit Typescript
Erreichen Sie eine OpenSSL-kompatible Verschlüsselung mit Java / PHP
Verkaufsautomat mit Java (domänengesteuert)
[Java] Machen Sie das Programm mit parallelStream 10x schneller
Ich habe versucht, eine Standardauthentifizierung mit Java durchzuführen
Einfaches Hindernisrennen mit Java-Verarbeitung
Die Schüler forderten Java SE 7/8 Bronze ohne Sorgfalt heraus.
Komfortablere Java-Codeabdeckung mit Jacoco 0.8.0
Machen Sie Java Stream Zeilenumbrüche mit Eclipse schön
Java SE Development Kit 8u161 - Einrichtung mit Alternativen
Einfacher LINE BOT mit Java Servlet