Verwenden Sie die Zwischenablage-API von JavaFX

Überblick

Java verfügt über java.awt.datatransfer.Clipboard zum Bearbeiten der Zwischenablage. Klassen sind verfügbar. Die Details stammen von Herrn Hishidama. Bitte lesen Sie diesen Artikel.

Hishidamas Technical Memo Page-Clipboard

Ich bin die Zwischenablage-API von JavaFX [javafx.scene.input.Clipboard](https://docs.oracle.com/javase/jp/8/javafx/api/javafx/scene/input/Clipboard Ich habe mich entschlossen, in .html) zu schauen.

Ausführungsumgebung

Java SE 1.8.0_u131
OS Windows 10
IDE IntelliJ IDEA 2017.1.3

javafx.scene.input.Clipboard

Stellt einen Betriebssystem-Clip dar, in dem Daten während Vorgängen wie Ausschneiden, Kopieren und Einfügen platziert werden können.

Nun, es ist eine Klasse, die alle möglichen Clip-bezogenen Dinge tun kann.


Let's try! Ich werde versuchen, den Code zu schreiben.

Code, der bei seiner Ausführung mit einer Ausnahme beendet wird


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

Fehler

Wie Sie der Pakethierarchie entnehmen können, ist javafx.scene.input.Clipboard eine JavaFX-Klasse und steht regulären Threads nicht zur Verfügung.

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)

Wenn Sie die Zwischenablage in einer normalen Anwendung betreiben möchten, verwenden Sie java.awt.datatransfer.Clipboard. ~~ Ende ~~

Codebeispiel, das funktioniert

Da es in jeder JavaFX-Anwendung verwendet werden kann, machen Sie die Klasse der Hauptmethode zu einer Unterklasse von javafx.application.Application.

Code, der gut funktioniert


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

Wenn Sie diesen Code ausführen, wird die aktuell in der Zwischenablage enthaltene Zeichenfolge ausgegeben.

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

Über die Methode

getContentTypes() Ruft die Art des Inhalts ab, der gespeichert wird.

getContentTypes()


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

Für Text

[[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]]

Für Bilddateien

[[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]]

Für Bilder im 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() Bestimmen Sie die Art des Inhalts, den Sie halten.

hasXX()Code zum Ausprobieren


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

Ausführungsergebnis

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>) Sie können den Wert nicht nur abrufen, sondern auch anschließen. Verwenden Sie Map und DataFormat zum Zusammenführen. Datei Format. Bitte notieren Sie den Namen.

Einzelwert

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

Wenn Sie nach dem Ausführen der Anwendung im Texteditor Strg + V drücken, wird der Text "Orange" eingefügt.

Mehrere Werte

Was aber, wenn der Inhalt mehrere Werte hat?

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

Wenn Sie nach dem Ausführen der Anwendung im Texteditor Strg + V drücken, wird der Text "Toast" eingefügt. Es scheint, dass nur einer in der Zwischenablage aufbewahrt werden kann.

clear() Diese Zwischenablage-API verfügt über eine eindeutige Methode.

Clipboard.clear()


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

Ausführungsergebnis


holding text
null

Was können Sie mit dieser API tun?

Da es sich um eine JavaFX-API handelt, wird ihre Verwendung zwangsläufig mit der GUI kombiniert.

1. Zeigen Sie den Wert an, den Sie aktuell in der Zwischenablage haben

Das war's.

2. Implementierung von Multi-Clip in der Editor-Anwendung

Wie der Name schon sagt, ist Multi-Clip eine Funktion, die mehrere Werte im Clip enthalten kann, und sie scheint eine Standardfunktion von UNIX-Texteditoren zu sein. Was würde passieren, wenn ich auf einem Umweg mit Leuten über diese Funktion sprechen würde? "Productive Programmer" hatte eine solche Geschichte.

Möglicherweise wird Ihnen von einem Mann, der etwa eine Stunde lang Sandalen trägt, gesagt, dass er diese seit der High School seit 20 Jahren benutzt.

3. Implementierung der Anwendung zur Überwachung der Zwischenablage

Wenn das Bild beispielsweise beibehalten wird, wird es automatisch in einer Datei gespeichert, oder wenn es sich um eine URL handelt, wird ein WebView-Fenster angezeigt ...


Implementierung einer einfachen Anwendung zur Überwachung der Zwischenablage

Also habe ich versucht, eine sehr einfache zu implementieren. Der Quellcode befindet sich im folgenden Repository auf GitHub.

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

Bildschirmfoto

sample.png

Es ist eine schlampige GUI-Anwendung, die eine Zeichenfolge oder ein Bild in der Zwischenablage in einem Fenster anzeigt und darauf klickt, um sie erneut in der Zwischenablage zu halten.

Clipstick-Ereignisüberwachung

Da javafx.scene.input.Clipboard keine reaktive API wie einen Ereignis-Listener hat, habe ich sie mithilfe von RxJava implementiert, um den Inhalt in Intervallen von 1 Sekunde zu überprüfen.

Beobachtbar, um die Zwischenablage zu überwachen


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

R.

Mit dem von RxJavaFX bereitgestellten RxJava Scheduler können JavaFX-Anwendungsthreads die Verarbeitung in RxJava ausführen. Ich werde. [Platform.runLater (Runnable)](https://docs.oracle.com/javase/jp/8/javafx/api/javafx/application/Platform.html#runLater-, das als Standard für Verbraucher usw. erstellt wurde. Sie können java.lang.Runnable-) verwenden. Wenn Sie jedoch einen Wert wie map oder filter zurückgeben müssen, ist dieser JavaFxScheduler hilfreich.

Null in RxJava2-Map usw. nicht zulässig

In RxJava2 führt die Rückgabe von null in der Karte zu einer 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)

Um dies zu vermeiden, stellen wir ein leeres Objekt zur Verfügung.

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

Zusammenfassung

Wir haben die Zwischenablage-API von JavaFX eingeführt und erklärt, wie eine einfache Anwendung damit implementiert wird. Wenn Sie keine JavaFX-Anwendung erstellen, ist dies nicht java.awt.datatransfer.Clipboard ). Die JavaFX-Zwischenablage-API verfügt über eine clear () -Methode.

Recommended Posts

Verwenden Sie die Zwischenablage-API von JavaFX
Verwenden Sie JavaFX / TextFormatter
Verwendung der Ketten-API
Verwenden Sie die Bulk-API mit RestHighLevelClient
[Rails] Verwenden Sie Cookies im API-Modus
[JavaFX] [Java8] Verwendung von GridPane