(Ported from betaveros.stash. Wow, I get syntax highlighting and footnotes! Probably years out of date though. I probably wrote this somewhere in 2012–2014, but am editing this parenthetical in 2021.)
A quick brief guide. At least, that’s how I planned it.
A lot of stuff is in the package java.awt.datatransfer
. Class Toolkit
is in java.awt
.
Some basic classes. The class Clipboard
is a clipboard, obviously. Its content is/will be an instance of the class Transferable
. Some content can be read as different types of objects depending on what you want; to choose which type you use an instance of DataFlavor
. It provides three basic ones: DataFlavor.imageFlavor
, DataFlavor.javaFileListFlavor
, and DataFlavor.stringFlavor
.
Okay, now step by step. This is the low-level method.
- Get the default clipboard with
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
- Get a transferable with
Transferable content = clipboard.getContents(null);
1 - Check if
content
can be read as the kind of object you want with(content != null) && content.isDataFlavorSupported(someFlavor)
- If it does, get the object with
content.getTransferData(someFlavor)
2.
If you just want a quick-and-dirty function:
static String getClipboard()
throws java.awt.datatransfer.UnsupportedFlavorException, IOException {
return (String) java.awt.Toolkit.getDefaultToolkit()
.getSystemClipboard()
.getData(java.awt.datatransfer.DataFlavor.stringFlavor);
}
For designing a Swing component, however, there are more integrated ways. This also allows drag-and-drop as well as cut-copy-paste, the conventional UI ideas. For many components (ex. JTextField
) the mechanisms are pretty much in place, and you can call setDragEnabled(true)
on them and be done. Further customizations are possible, particularly for complex things JList, JTable, JTree
; I’ll just skip them today. The first thing is defining/subclassing a TransferHandler
, which will be asked to handle all of this stuff by Swing internals:
class SomeTransferHandler extends TransferHandler {
// Export actions: drag, cut/copy, callback
int getSourceActions(JComponent c) {
return COPY_OR_MOVE;
// choose from COPY, MOVE, COPY_OR_MOVE, LINK, NONE
}
Transferable createTransferable(JComponent c) { /* ... */ }
void exportDone(JComponent c, Transferable t, int action) { /* ... */ }
// Import actions: drop, paste
public boolean canImport(TransferSupport supp) { /* ... */ }
public boolean importData(TransferSupport supp) { /* ... */ }
}
Note that you do not have to define all of the methods, only the ones you need. TransferHandler
is not abstract, although directly instantiating one is probably not a good idea.
TransferHandler.TransferSupport
is3 a wrapper around Transferable
containing also where the transfer is coming from and of what type it is. The transferable is extracted with getTransferable()
, but the wrapper also directly has data-flavor compatibility checking methods4. Go look its methods up.
Okay, now that you have a handler set up, how do you get it used? someJComponent.setTransferHandler(someTransferHandler)
will allow the handler to handle the transfer events. For cc&p, you can get corresponding Action
s from TransferHandler.get[Cut|Copy|Paste]Action()
(yes, static method).
The argument is a handler of type
ClipboardOwner
which needs one methodlostOwnership(Clipboard c, Transferable t)
that is called when the clipboard no longer contains your content. I guess you use it to free resources? I don’t need it though.↩It throws checked exceptions
UnsupportedFlavorException
andIOException
. My former self would hope that you have an IDE that would tell you that and salutes you if you don’t. Now, I just think whatever, if you’re writing Scala like me then you don’t even care.↩At least I think of it as one, but I don’t know if everybody’s definition of “wrapper” matches mine. Oh well.↩
isDataFlavorSupported(DataFlavor)
andgetDataFlavors()
; the latter returns an array. The documentation says these are faster than extracting theTransferable
and querying it.↩