Utilisez l'API Clipboard de JavaFX

Aperçu

Java a java.awt.datatransfer.Clipboard pour manipuler le presse-papiers. Des cours sont disponibles. Les détails sont écrits par M. Hishidama, veuillez donc lire cet article.

Page de mémo technique de Hishidama - Presse-papiers

Je suis l'API Clipboard de JavaFX [javafx.scene.input.Clipboard](https://docs.oracle.com/javase/jp/8/javafx/api/javafx/scene/input/Clipboard J'ai décidé de regarder dans .html).

Environnement d'exécution

Java SE 1.8.0_u131
OS Windows 10
IDE IntelliJ IDEA 2017.1.3

javafx.scene.input.Clipboard

Représente un clip du système d'exploitation dans lequel les données peuvent être placées lors d'opérations telles que couper, copier et coller.

Eh bien, c'est une classe qui peut faire toutes sortes de choses liées aux clips.


Let's try! J'essaierai d'écrire le code.

Code qui se termine avec une exception lors de l'exécution


import javafx.scene.input.Clipboard;

import java.util.concurrent.atomic.AtomicLong;
import java.util.stream.Stream;

public class Main {
    public static void main(String[] args) {
        final Clipboard cb = Clipboard.getSystemClipboard();
        System.out.println(cb.getString());;
    }
}

Échec

Comme vous pouvez le voir dans la hiérarchie des packages, javafx.scene.input.Clipboard est une classe JavaFX et n'est pas disponible pour les threads normaux.

Exception in thread "main" java.lang.IllegalStateException: This operation is permitted on the event thread only; currentThread = main
	at com.sun.glass.ui.Application.checkEventThread(Application.java:443)
	at com.sun.glass.ui.ClipboardAssistance.<init>(ClipboardAssistance.java:40)
	at com.sun.javafx.tk.quantum.QuantumToolkit.getSystemClipboard(QuantumToolkit.java:1200)
	at javafx.scene.input.Clipboard.getSystemClipboardImpl(Clipboard.java:413)
	at javafx.scene.input.Clipboard.getSystemClipboard(Clipboard.java:178)
	at jp.toastkid.sandbox.Sandbox.main(Sandbox.java:10)

Donc, si vous souhaitez utiliser le presse-papiers dans une application normale, utilisez java.awt.datatransfer.Clipboard. ~~ Fin ~~

Exemple de code qui fonctionne

Puisqu'il peut être utilisé dans n'importe quelle application JavaFX, faites de la classe de la méthode main une sous-classe de javafx.application.Application.

Code qui fonctionne bien


import javafx.application.Application;
import javafx.scene.input.Clipboard;
import javafx.stage.Stage;

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

    @Override
    public void start(Stage primaryStage) throws Exception {
        Clipboard cb = Clipboard.getSystemClipboard();
        System.out.println(cb.getString());
    }
}

L'exécution de ce code affichera la chaîne actuellement contenue dans le presse-papiers.

final Clipboard cb = Clipboard.getSystemClipboard();
System.out.println(cb.getString());

À propos de la méthode

getContentTypes() Obtient le type de contenu en attente.

getContentTypes()


System.out.println(cb.getContentTypes());

Pour le texte

[[text/uri-list], [JAVA_DATAFLAVOR:application/x-java-jvm-local-objectref; class=com.intellij.codeInsight.editorActions.FoldingData], [text/plain], [ms-stuff/oem-text], [text/rtf], [text/html], [ms-stuff/locale]]

Pour les fichiers image

[[FileName], [message/external-body;access-type=clipboard;index=1;size=28453;name="650contribution.png "], [AsyncFlag], [DataObjectAttributesRequiringElevation], [application/x-java-file-list, java.file-list], [FileNameW], [ms-stuff/preferred-drop-effect], [message/external-body;access-type=clipboard;index=2;size=220376;name="sample_images_1.jpg "], [text/uri-list], [message/external-body;access-type=clipboard;index=0;size=119242;name="sample_images_2.jpg "], [Shell Object Offsets], [Shell IDList Array], [DataObjectAttributes]]

Pour les images sur Internet

[[text/uri-list], [application/x-java-rawimage], [text/_moz_htmlinfo], [text/html;cf=49474], [application/x-java-file-list, java.file-list], [text/_moz_htmlcontext], [application/x-moz-nativeimage], [text/html], [application/x-moz-file-promise-url], [application/x-moz-file-promise-dest-filename], [cf17], [ms-stuff/preferred-drop-effect]]

hasXX() Déterminez le type de contenu que vous détenez.

hasXX()Code à essayer


System.out.println(cb.hasString());
System.out.println(cb.hasUrl());
System.out.println(cb.hasHtml());
System.out.println(cb.hasRtf());
System.out.println(cb.hasImage());
System.out.println(cb.hasFiles());

Résultat d'exécution

T: true F: false

Method name Text Local image file Web image file URL on Browser
hasString() T F F T
hasUrl() T T T F
hasHtml() T F T F
hasRtf() T F F F
hasImage() F F T F
hasFiles() F T T F

setContent(Map<DataFormat, Object>) Non seulement vous pouvez récupérer la valeur, mais vous pouvez également la brancher. Utilisez Map et DataFormat pour la fusion. Format Dat ** a **. Veuillez noter le nom.

Valeur unique

final Map<DataFormat, Object> content = new HashMap<>();
content.put(DataFormat.PLAIN_TEXT, "Orange");
cb.setContent(content);

Si vous appuyez sur Ctrl + V sur l'éditeur de texte après avoir exécuté l'application, le texte "Orange" sera collé.

Valeurs multiples

Mais que faire si le contenu a plusieurs valeurs?

final Map<DataFormat, Object> content = new HashMap<>();
content.put(DataFormat.URL, "https://www.yahoo.co.jp");
content.put(DataFormat.PLAIN_TEXT, "Toast");
cb.setContent(content);

Si vous appuyez sur Ctrl + V sur l'éditeur de texte après avoir exécuté l'application, le texte "Toast" sera collé. Il semble qu'un seul puisse être conservé dans le presse-papiers.

clear() Cette API Clipboard a une méthode claire.

Clipboard.clear()


System.out.println(clipboard.getString());
clipboard.clear();
System.out.println(clipboard.getString());

Résultat d'exécution


holding text
null

Que pouvez-vous faire avec cette API?

Puisqu'il s'agit d'une API JavaFX, son utilisation est inévitablement combinée avec l'interface graphique.

1. Affichez la valeur que vous avez actuellement dans le presse-papiers

Eh bien c'est ça.

2. Implémentation du multi-clip dans l'application d'édition

Comme son nom l'indique, le multi-clip est une fonction qui vous permet de stocker plusieurs valeurs dans le clip, et cela semble être une fonction standard des éditeurs de texte UNIX. Que se passerait-il si je parlais aux gens de cette fonction dans un détour, "Productive Programmer" avait une telle histoire.

Un homme portant des sandales vous dira peut-être depuis environ une heure qu'il l'utilise depuis 20 ans depuis le lycée.

3. Mise en œuvre de l'application de surveillance du presse-papiers

Par exemple, si l'image est conservée, elle est automatiquement enregistrée dans un fichier, ou s'il s'agit d'une URL, une fenêtre WebView s'affiche ...


Implémentation d'une application de surveillance de presse-papiers

J'ai donc essayé d'en implémenter un très simple. Le code source se trouve dans le référentiel suivant sur GitHub.

https://github.com/toastkidjp/clipboard_observer_app/tree/qiita

capture d'écran

sample.png

C'est une application GUI bâclée qui affiche des chaînes ou des images contenues dans le presse-papiers dans une fenêtre et clique dessus pour les retenir dans le presse-papiers.

Surveillance des événements Clipstick

Étant donné que javafx.scene.input.Clipboard n'a pas d'API réactive telle qu'un écouteur d'événements, je l'ai implémenté en utilisant RxJava pour vérifier le contenu à des intervalles d'une seconde.

Observable pour surveiller le presse-papiers


Observable.interval(1, TimeUnit.SECONDS)
          .observeOn(JavaFxScheduler.platform())
          .map(l -> getStringOrEmpty())
          .filter(str -> !str.isEmpty())
          .subscribe(stringConsumer, Throwable::printStackTrace);

RxJavaFX JavaFxScheduler

Le planificateur RxJava fourni par RxJavaFX permet aux threads d'application JavaFX d'effectuer le traitement dans RxJava. Je vais. [Platform.runLater (Runnable)](https://docs.oracle.com/javase/jp/8/javafx/api/javafx/application/Platform.html#runLater-] qui est préparé en standard pour Consumer etc. Vous pouvez utiliser java.lang.Runnable-), mais si vous devez renvoyer une valeur comme map ou filter, ce JavaFxScheduler est utile.

Null non autorisé dans la carte RxJava2, etc.

Dans RxJava2, le renvoi de null dans la carte entraînera une NullPointerException.

java.lang.NullPointerException: The mapper function returned a null value.
	at io.reactivex.internal.functions.ObjectHelper.requireNonNull(ObjectHelper.java:39)
	at io.reactivex.internal.operators.observable.ObservableMap$MapObserver.onNext(ObservableMap.java:59)
	at io.reactivex.internal.operators.observable.ObservableObserveOn$ObserveOnObserver.drainNormal(ObservableObserveOn.java:200)
	at io.reactivex.internal.operators.observable.ObservableObserveOn$ObserveOnObserver.run(ObservableObserveOn.java:252)
	at io.reactivex.rxjavafx.schedulers.JavaFxScheduler$JavaFxWorker$QueuedRunnable.run(JavaFxScheduler.java:87)
	at io.reactivex.rxjavafx.schedulers.JavaFxScheduler$JavaFxWorker.run(JavaFxScheduler.java:158)
	at com.sun.javafx.application.PlatformImpl.lambda$null$173(PlatformImpl.java:295)
	at java.security.AccessController.doPrivileged(Native Method)
	at com.sun.javafx.application.PlatformImpl.lambda$runLater$174(PlatformImpl.java:294)
	at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
	at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
	at com.sun.glass.ui.win.WinApplication.lambda$null$148(WinApplication.java:191)
	at java.lang.Thread.run(Thread.java:748)

Un objet Empty est fourni pour éviter cela.

private static final Image EMPTY_IMAGE = new WritableImage(1, 1);

Résumé

Nous avons présenté l'API Clipboard de JavaFX et expliqué comment implémenter une application simple en l'utilisant. Si vous ne créez pas une application JavaFX, ce n'est pas java.awt.datatransfer.Clipboard. L'API JavaFX Clipboard a une méthode clear ().

Recommended Posts

Utilisez l'API Clipboard de JavaFX
Utiliser JavaFX / TextFormatter
Comment utiliser l'API Chain
Utiliser l'API Bulk avec RestHighLevelClient
[Rails] Utiliser des cookies en mode API
[JavaFX] [Java8] Comment utiliser GridPane