Java 侦听剪贴板更改,检查所有权?

Java 侦听剪贴板更改,检查所有权?,java,clipboard,Java,Clipboard,如果字符串被复制到系统剪贴板,我希望得到通知。当从同一源应用程序复制新字符串时,FlavorListener将不会获得事件。为了在复制另一个字符串时得到通知,我从剪贴板中读取该字符串,将其转换为一个SrtingSelection,它能够获得所有权,然后将其放回剪贴板。现在我得到了两次通知,一次是StringSelection失去了所有权,一次是它收回了所有权。有没有办法直接检查所有权,而不是存储字符串并检查它是否等于新的所有权? 以下是我目前的代码: import java.awt.Toolk

如果字符串被复制到系统剪贴板,我希望得到通知。当从同一源应用程序复制新字符串时,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();
            }
        }
    }
}

我希望你能理解我的蹩脚英语:-(

为避免双重通知,请在设置新剪贴板内容之前删除flavor listener,并在设置剪贴板内容之后再次添加listener

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

前面的答案很可能奏效

真正的解决方法是只监视所有权更改事件。监视器在监视剪贴板时以所有者身份占用剪贴板,因此当任何应用程序更改剪贴板时,所有权都会更改,因此这将可靠地指示剪贴板内容更改。但是,此方法必须有足够的等待时间才能工作在访问剪贴板并重新占用剪贴板之前,所有权更改事件发生后,(发现200毫秒正在工作)

marc weber在

我已经验证了我的目的。如果需要,我可以在这里发布解决方案

我认为这会奏效:)

import java.awt.AWTEvent;
导入java.awt.EventQueue;
导入java.awt.Toolkit;
导入java.awt.datatransfer.Clipboard;
导入java.awt.datatransfer.ClipboardOwner;
导入java.awt.datatransfer.DataFlavor;
导入java.awt.datatransfer.StringSelection;
导入java.awt.datatransfer.transfer;
导入java.awt.datatransfer.UnsupportedFlavorException;
导入java.awt.event.ActionEvent;
导入java.awt.event.InputEvent;
导入java.io.IOException;
导入java.util.Observable;
导入java.util.Observer;
导入javax.swing.JFrame;
公共最终类ClipboardMonitor扩展了可观察的实现ClipboardOwner{
私有静态剪贴板监视器=null;
公共剪贴板监视器(){
无报酬();
}
私人无效收益权(){
剪贴板clip=Toolkit.getDefaultToolkit().getSystemClipboard();
试一试{
可转移内容=clip.getContents(null);
DataFlavor[]f=content.getTransferDataFlavors();
布尔图像检测=假;
对于(int i=0;iimport 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);
  }