Suggerimento Java 61: taglia, copia e incolla in Java

Questo articolo ti darà una buona comprensione di come inviare e ottenere informazioni dagli appunti in Java. Imparerai anche come gestire i diversi tipi di dati disponibili. Infine, tratteremo le molteplici personalità degli appunti e il modo in cui forniscono supporto per più di un tipo di dati.

Java offre due tipi di appunti: locale e di sistema. Gli appunti locali sono disponibili solo all'interno della macchina virtuale in cui è in esecuzione l'applet o l'applicazione. Tuttavia, a differenza di alcuni sistemi operativi che ti limitano a un solo appunti, Java ti consente di avere tutti gli appunti locali che desideri. Accedere a un particolare appunti locale è facile come fare riferimento ad esso per nome.

Gli appunti di sistema sono collegati direttamente al sistema operativo peer, consentendo all'applicazione di trasferire le informazioni tra tutte le applicazioni in esecuzione su quel sistema operativo. Uno svantaggio dell'utilizzo degli appunti di sistema è che puoi trasferire solo dati di testo. Altri tipi di oggetti non sono supportati dagli appunti di sistema. Con un po 'di fortuna, questo problema verrà risolto nella prossima versione di JDK.

Prima di andare oltre, diamo uno sguardo a tutte le classi coinvolte nella manipolazione degli appunti. Queste classi, elencate nella tabella seguente, fanno tutte parte del pacchetto java.awt.datatransfer .

Elenco di tutte le classi nel pacchetto java.awt.datatransfer
Nome genere Descrizione
Clipboard Classe Si occupa di tutto ciò che è trasferibile
ClipboardOwner Interfaccia Ogni classe che si occupa degli appunti deve implementare questa interfaccia. Questa interfaccia viene utilizzata per notificare quando i dati originariamente inseriti negli appunti sono stati sovrascritti
Dataflavor Classe Rappresenta tutti i tipi di dati che supportano il trasferimento
StringSelection Classe Un tipo di trasferibile fornito con Java
Transferable Interfaccia Wrapper per gli oggetti passati negli appunti
UnsupportedFlavor Exception Classe Eccezione generata da trasferibile per un sapore di dati non supportato

Altro sulle classi degli appunti

Andiamo più in profondità nella nostra esplorazione del java.awt.datatransferpacchetto esaminando in dettaglio ogni classe.

La classe Appunti

La Clipboardclasse è il tuo link per accedere agli appunti. Include tre metodi, definiti nella tabella seguente:

Classe appunti
Metodo Descrizione
String getName () Ottieni il nome degli appunti
void setContents (Transferable, ClipboardOwner) Imposta il contenuto degli appunti insieme all'oggetto proprietario
Transferable getContent (Object) Ottieni il contenuto degli appunti sotto forma di un oggetto trasferibile. L'oggetto passato come parametro è il proprietario

I tre Clipboardmetodi di classe sopra ti consentono di nominare gli appunti, inviargli informazioni o ottenere informazioni da esso. L'accesso agli appunti di sistema o la creazione di un appunti locale è diverso e richiede un po 'più di discussione. Per accedere agli appunti di sistema, assegnare alla Clipboardclasse un riferimento dagli appunti di sistema , ad esempio:

Clipboard clipboard = getToolkit ().getSystemClipboard ();

D'altra parte, per creare una clipboard locale è sufficiente creare un Clipboardoggetto con il nome che si desidera assegnargli, ad esempio:

Clipboard clipboard = new Clipboard ("My first clipboard");

L'accesso agli appunti di sistema o la creazione di un appunti locale è diverso ma semplice.

L'interfaccia ClipboardOwner

Poiché Java è un linguaggio multipiattaforma e poiché i sistemi operativi si comportano in modo diverso rispetto agli appunti, gli autori del linguaggio Java hanno dovuto escogitare un meccanismo per gestire le sottili differenze. Questo è il motivo della presenza ClipboardOwnerdell'interfaccia. La sua unica funzione è informare il proprietario degli appunti quando i suoi dati vengono sovrascritti da qualcun altro. Può anche segnalare a un'applicazione quando rilasciare una risorsa associata ai dati.

In un'applicazione reale, il lostOwnershipmetodo potrebbe essere utilizzato per impostare un flag che informa la tua applicazione sulla disponibilità dei dati negli appunti. Microsoft Word, sebbene non sia scritto in Java, è un buon esempio di questo meccanismo al lavoro in un'applicazione. Ogni volta che inserisci qualcosa negli appunti in Word e poi esci, viene visualizzata una finestra di dialogo che ti informa che i dati sono negli appunti. Ti verrà quindi chiesto se desideri lasciare i dati negli appunti.

L'implementazione ClipboardOwnerdell'interfaccia è relativamente semplice perché c'è solo un metodo da implementare. Questo metodo farà sì che il tuo programma ceda la proprietà degli appunti.

La classe DataFlavor

La DataFlavorclasse viene utilizzata per rappresentare il tipo di un oggetto. Non sei limitato a un tipo di dati (o tipo) per oggetto. E, come noi, i tuoi oggetti possono avere più personalità! Ad esempio, una classe immagine può essere rappresentata come una classe Java o come un array di bit (GIF, JPEG e così via). In realtà, una DataFlavorclasse è un wrapper per un tipo MIME. Lo standard MIME è ampio, quindi non ci sono praticamente limiti ai dati che possono essere trasferiti negli appunti. (Una discussione sullo standard MIME non rientra nell'ambito di questo articolo, ma è possibile trovare ulteriori informazioni nella sezione Risorse).

Come esempio di un gusto dati, scoprirai che la StringSelectionclasse ha due gusti basati sui tipi MIME. Nell'implementazione c'è "application / x-java-serialized-object", e il secondo è "text / plain; charset = unicode". In effetti, questa implementazione ci dice che possiamo recuperare il testo dagli appunti come Stringclasse ( application/x-java-serialized-object) o come testo semplice ( text/plain; charset=unicode).

Esistono due modi per creare un file DataFlavor. Tu puoi scrivere:

public DataFlavor (representationClass, String humanRepresentationName)

Questo costruttore creerà un nuovo sapore di dati che rappresenta una classe Java. Il reso DataFlavoravrà representationClass = representationClasse a mimeType = application/x-java-serialized-object. Ad esempio, quanto segue creerebbe un DataFlavorper java.awt.Button:

DataFlavor (Class.forName ("java.awt.Button"), "AWT Button");

Ora, questo secondo costruttore

public DataFlavor (String mimeType, String humanRepresentationName)

costruirà un DataFlavorusando a MimeType. Il reso DataFlavorsarà basato sul MimeType. Se MimeTypeè application/x-java-serialized-object, il risultato sarà lo stesso di se avessi chiamato il costruttore precedente. Tuttavia, il reso DataFlavorsarà representationClass= InputStream and mimeType =mimeType. Ad esempio, la seguente chiamata creerebbe un sapore di testo normale:

public DataFlavor ("text/plain; charset=unicode", "Unicode");

La tabella seguente mostra i metodi della DataFlavorclasse.

Classe DataFlavor
Metodi Descrizione
boolean equals (DataFlavor) Verifica se il DataFlavor fornito è uguale al DataFlavor rappresentato da questa classe
String getHumanPresentableName () Restituisce il nome rappresentabile umano per il formato rappresentato da questo DataFlavor
void setHumanPresentableName (String) Imposta il nome della rappresentazione umana per questo DataFlavor
String getMimeType () Ottieni la stringa di tipo MIME rappresentata da questo DataFlavor
Class getRepresentationClass () Restituisce la classe che rappresenta questa classe

L'interfaccia trasferibile

L' Transferableinterfaccia deve essere implementata da tutte le classi che si desidera inviare negli appunti, quindi la Clipboardclasse comprenderà solo le classi che sono state inserite Transferablenell'interfaccia. L' Transferableinterfaccia comprende tre metodi:

Interfaccia trasferibile
Metodi Descrizione
DataFlavor getTransferDataFlavor () Restituisce una matrice di DataFlavor che rappresenta l'oggetto
boolean isDataFlavorSupported (DataFlavor) Verifica se il DataFlavor fornito è supportato
Object getTransferData (DataFlavor) Restituisce l'oggetto rappresentato dal DataFlavor fornito

Questo conclude il nostro tour di tutte le classi coinvolte nella gestione degli appunti. Abbiamo visto che per accedere agli appunti dobbiamo creare un Clipboardoggetto o ottenere un riferimento agli appunti di sistema. Poiché gli appunti accettano solo oggetti di tipo Transferable, l'oggetto che si desidera inviare agli appunti deve implementare questa interfaccia. Infine, tutti gli oggetti negli appunti hanno gusti che sono rappresentati dalla DataFlavorclasse, che in realtà è un wrapper per i tipi MIME.

Nelle prossime sezioni metteremo in pratica ciò che abbiamo appreso.

La ricetta per l'utilizzo degli appunti

Il modo in cui queste varie classi accedono agli appunti può creare confusione. Fortunatamente esiste una ricetta semplice, che prevede i seguenti passaggi:

Passaggio 1. Creare una classe denominata xxxxSelection . Qui, xxx dovrebbe nominare il tipo rappresentato da questo sapore. Ad esempio, ImageSelectionsarebbe un buon nome per un sapore di immagine. Questa convenzione di denominazione è solo un suggerimento, ovviamente. Sto seguendo la convenzione d'uso stabilita con quella StringSelectionfornita nel JDK, ma puoi nominare questa classe come preferisci. È importante ricordare che questo oggetto deve implementare le interfacce Transferablee ClipboardOwner. Se hai intenzione di trasferire del testo, StringSelectiondovresti usare la classe.

Passaggio 2. Definire una classe per accedere agli appunti . Per accedere a un clipboard locale, utilizzare la seguente chiamata: Clipboard clipboard = new Clipboard ("name"). Per accedere al sistema operativo appunti tra pari, utilizzare questa chiamata invece: Clipboard clipboard = getToolkit ().getSystemClipboard ().

Passaggio 3. Impostare il contenuto degli appunti . A tale scopo, utilizzare il setContentmetodo nella Clipboardclasse, dove il primo parametro è un oggetto che implementa una Transferable( xxxxSelectionclasse creata nel passaggio 1) e il secondo parametro è un riferimento alla classe che chiama questo metodo.

Passaggio 4. Ottieni il contenuto degli appunti . Usa il getContentmetodo della Clipboardclasse. Questo metodo restituirà una classe di tipo Transferable.

Passaggio 5. Implementare una "operazione di taglio" . Per fare ciò, è necessario cancellare manualmente i dati una volta copiati negli appunti. Java non fornisce l'implementazione di un'operazione di taglio.

Dopo questo breve tour delle classi che coinvolgono la manipolazione degli appunti, seguiremo la ricetta suggerita per scrivere una semplice applet che trasferisca il testo negli appunti di sistema.

Listato 1

Esaminiamo questa applet:

Listato 1

Quanto segue è una spiegazione di righe di codice specifiche nel listato 1.

Riga 9: definire la classe applet1per estendere la Appletclasse e implementare l' ClipboardOwnerinterfaccia.

Riga 17: Definisci un oggetto appunti.

Riga 26: imposta l'oggetto appunti negli appunti del sistema operativo peer.

Righe da 45 a 47: implementa l'unico metodo in questa interfaccia. In questo articolo non usiamo il lostOwnershipmetodo ma stampiamo semplicemente un messaggio sulla console. Puoi sperimentare questo metodo copiando del testo negli appunti usando questa applet e poi copiando qualcos'altro da un'altra applicazione. Dovresti vedere il messaggio di perdita della proprietà nella console Java, perché i dati che sono stati inseriti negli appunti (utilizzando l'applet Java) sono stati sovrascritti dall'altra applicazione.

Riga 52: Definisci una classe del tipo StringSelectionche implementa un sapore di dati di testo. Otteniamo quindi il contenuto del campo di testo di origine.

Riga 53: Imposta il contenuto degli appunti sulla fieldContentclasse che abbiamo definito nella riga precedente. Notare che dobbiamo fornire al proprietario di questa classe, in questo caso, questa applet.

Riga 61: Definisci un oggetto di tipo Transferableper ricevere il contenuto degli appunti.

Riga 63: convalida due cose. Innanzitutto, gli appunti sono vuoti? Secondo, il contenuto degli appunti ha il sapore giusto? In questo caso stiamo cercando un file stringFlavor.

Riga 67: ottieni il contenuto degli appunti in una variabile stringa. Per fare ciò, chiamiamo il getTransferDatametodo con il sapore richiesto. In questo caso, abbiamo bisogno di un DataFlavor.stringFlavortipo.

Riga 69: imposta il contenuto del campo di testo di destinazione sul contenuto degli appunti.

Puoi sperimentare con questa applet trasferendo il testo tra questa applet e un'altra applet Java, o tra un'applet Java e un programma nativo, come Blocco note, per coloro che eseguono Microsoft Windows.

Listato 2

Nel secondo esempio, scriveremo un'applet che copia un'immagine negli appunti. L'immagine implementerà il proprio sapore.

Listato 2

Quanto segue è una spiegazione di righe di codice specifiche nel listato 2.

Riga 27: crea un oggetto appunti che faccia riferimento a un appunti locale.

Riga 41: imposta il sourImagecontrollo su Image.gif.

Righe dalla 44 alla 50: implementa il lostOwnershipmetodo. Stampiamo semplicemente un messaggio sulla console Java.

Riga 6: crea un ImageSelectionoggetto basato sull'immagine nel sourceImagecontrollo.

Riga 57: Imposta il contenuto degli appunti con l' ImageSelectionoggetto.

Riga 66: ottieni il contenuto degli appunti.

Riga 68: assicurati che il contenuto non sia nullo e che il gusto che stiamo cercando sia supportato.

Riga 71: ottieni i dati nel gusto appropriato.

Riga 72: imposta il destinationImagecontrollo sul contenuto appena ottenuto.

Riga 90: definisci la ImageSelectionclasse.

Riga 93: Definisci un array di DataFlavorchiamate supportedFlavorscon un elemento ( imageFlavor).

Riga 102: crea il sapore dell'immagine. Il sapore creato si basa sul java.awt.Imagecon il nome di rappresentazione "Immagine".

Righe dalla 111 alla 130: implementa i Transferablemetodi.

Riga 123: restituisce il contenuto degli appunti con questo metodo.

Riga 125: convalida il sapore. Se la versione richiesta è supportata, viene restituito l'oggetto immagine. In caso contrario, viene generata un'eccezione.

Nel Listato 1, abbiamo usato il data flavour ( StringSelection) predefinito per inviare il testo agli appunti di sistema. Nel Listato 2, siamo andati oltre implementando il nostro sapore di dati java.awt.Image.