如果将字符串复制到系统剪贴板,我希望收到通知。从同一源应用程序复制新字符串时,FlavorListener将不会获取事件。为了在复制另一个字符串时获得通知,我从剪贴板中读取字符串,将其转换为SrtingSelection,它可以获取所有权,并将其放回剪贴板。一旦StringSelection失去了所有权并且一旦收回它,我就得到了两次通知。有没有办法直接检查所有权,而不是存储字符串并检查它等于新的字符串? 到目前为止,这是我的代码:
import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.FlavorEvent;
import java.awt.datatransfer.FlavorListener;
import java.awt.datatransfer.StringSelection;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.IOException;
public class Main {
public static void main(String[] args) throws Exception {
// The clipboard
final Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard();
// read clipboard and take ownership to get the FlavorListener notified
// when the content has changed but the owner has not
processClipboard(cb);
cb.addFlavorListener(new FlavorListener() {
@Override
public void flavorsChanged(FlavorEvent e) {
processClipboard(cb);
}
});
// keep thread for testing
Thread.sleep(100000L);
}
public static void processClipboard(Clipboard cb) {
// gets the content of clipboard
Transferable trans = cb.getContents(null);
if (trans.isDataFlavorSupported(DataFlavor.stringFlavor)) {
try {
// cast to string
String s = (String) trans
.getTransferData(DataFlavor.stringFlavor);
System.out.println(s);
// only StringSelection can take ownership, i think
StringSelection ss = new StringSelection(s);
// set content, take ownership
cb.setContents(ss, ss);
} catch (UnsupportedFlavorException e2) {
e2.printStackTrace();
} catch (IOException e2) {
e2.printStackTrace();
}
}
}
}
我希望你能理解我的坏英语: - (
答案 0 :(得分:5)
之前的答案即将开始。
真正的解决方法是只监控所有权变更事件。监视器在监视剪贴板时占用剪贴板作为所有者,因此当任何应用程序更改剪贴板时,所有权将更改,因此这将可靠地指示剪贴板内容更改。但是,在访问剪贴板并重新占用剪贴板之前,所有权更改事件之后,此方法必须有足够的等待工作(发现200毫秒才能正常工作)。
这个解决方案已经提供并证明是由marc weber在 http://www.coderanch.com/t/377833/java/java/listen-clipboard
我已经验证了我的目的。如果需要,我可以在这里发布解决方案。
于
答案 1 :(得分:1)
要避免双重通知,请在设置新剪贴板内容之前删除flavor侦听器,并在设置剪贴板内容后再次添加侦听器。
public class NewClass implements FlavorListener, ClipboardOwner{
private Clipboard clip = Toolkit.getDefaultToolkit().getSystemClipboard();
public NewClass() {
System.out.println("NewClass constructor");
clip.setContents(clip.getContents(null), this);
clip.addFlavorListener(this);
try {
Thread.sleep(100000L);
}
catch (InterruptedException e) {
}
}
@Override
public void flavorsChanged(FlavorEvent e) {
System.out.println("ClipBoard Changed!!!");
clip.removeFlavorListener(this);
clip.setContents(clip.getContents(null), this);
clip.addFlavorListener(this);
}
@Override
public void lostOwnership(Clipboard arg0, Transferable arg1) {
System.out.println("ownership losted");
}
}
答案 2 :(得分:0)
我认为这会奏效:)
import java.awt.AWTEvent;
import java.awt.EventQueue;
import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.ClipboardOwner;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.StringSelection;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.event.ActionEvent;
import java.awt.event.InputEvent;
import java.io.IOException;
import java.util.Observable;
import java.util.Observer;
import javax.swing.JFrame;
public final class ClipboardMonitor extends Observable implements ClipboardOwner {
private static ClipboardMonitor monitor = null;
public ClipboardMonitor() {
gainOwnership();
}
private void gainOwnership() {
Clipboard clip = Toolkit.getDefaultToolkit().getSystemClipboard();
try {
Transferable content = clip.getContents(null);
DataFlavor[] f = content.getTransferDataFlavors();
boolean imageDetected = false;
for (int i = 0; i < f.length; i++) {
// System.out.println("Name: " + f[i].getHumanPresentableName());
// System.out.println("MimeType: " + f[i].getMimeType());
// System.out.println("PrimaryType: " + f[i].getPrimaryType());
// System.out.println("SubType: " + f[i].getSubType());
if (f[i].equals(DataFlavor.imageFlavor)) {
imageDetected = true;
break;
}
}
if (imageDetected) {
System.out.println("Image content detected");
Transferable t = new Transferable() {
public DataFlavor[] getTransferDataFlavors() {
return new DataFlavor[] { DataFlavor.stringFlavor };
}
public boolean isDataFlavorSupported(DataFlavor flavor) {
return false;
}
public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException {
return "dummy text instead of snapshot image";
}
};
clip.setContents(t, this);
} else {
clip.setContents(content, this);
}
setChanged();
notifyObservers(content);
} catch (IllegalArgumentException istateexception) {
istateexception.printStackTrace();
} catch (Exception ioexception) {
ioexception.printStackTrace();
}
}
private int getCurrentEventModifiers() {
int modifiers = 0;
AWTEvent currentEvent = EventQueue.getCurrentEvent();
if (currentEvent instanceof InputEvent) {
modifiers = ((InputEvent) currentEvent).getModifiers();
} else
if (currentEvent instanceof ActionEvent) {
modifiers = ((ActionEvent) currentEvent).getModifiers();
}
return modifiers;
}
public void lostOwnership(Clipboard clipboard, Transferable contents) {
System.out.println("Ownership lost ...");
new Thread(new Runnable() {
public void run() {
try {
Thread.sleep(200);
gainOwnership();
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
public void flushClipboard() {
Toolkit.getDefaultToolkit().getSystemClipboard().setContents(new StringSelection(""), null);
}
public static final ClipboardMonitor getMonitor() {
if (monitor == null)
monitor = new ClipboardMonitor();
return (monitor);
}
public static void main(String[] args) {
JFrame f = new JFrame();
ClipboardMonitor monitor = ClipboardMonitor.getMonitor();
monitor.addObserver(new Observer() {
public void update(Observable o, Object arg) {
System.out.println("Clipboard has been regained!");
}
});
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(500, 100);
f.setVisible(true);
}
}