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

发布于 2024-10-28 04:42:53 字数 2118 浏览 5 评论 0原文

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

我希望你能理解我糟糕的英语:-(

I want to be notified if a string is copied to the system clipboard. When a new string is copied from the same source application, the FlavorListener won't get an event. To get informed when another string is copied, i read the string from the clipboard, convert it to a SrtingSelection, which is able to take the ownership, and put it back to the clipboard. Now I got informed twice, once the StringSelection lost ownership and once it takes it back. Is there a way to check for the ownership directly, instead of storing the string and check it equals the new one?
Here is my code so far:

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

I hope you understand my bad english :-(

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

晌融 2024-11-04 04:42:53

之前的答案即将生效。

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

该解决方案由 Marc Weber 提供并证明有效
http://www.coderanch.com/t/377833/java/java /listen-clipboard

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

The previous answer is close to be working.

The real cure is to instead just monitor the event of ownership change. By the monitor's occupying the clipboard as owner when monitoring the clipboard, so when any application changes the clipboard, the ownership would change, so this would reliably indicate the clipboard content change. However, this approach must have sufficient wait to work, (200 ms was found to be working) after an ownership change event before accessing the clipboard and re-occupying the clipboard.

This solution was provided and proved to be working by marc weber at
http://www.coderanch.com/t/377833/java/java/listen-clipboard

I have verified for my purpose. If needed, I can post the solution here.

Yu

独闯女儿国 2024-11-04 04:42:53

为了避免双重通知,请在设置新的剪贴板内容之前删除风味侦听器,并在设置剪贴板内容后再次添加侦听器。

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

To avoid double notification remove the flavor listener before setting the new clipboard content and add the listener again after setting clipboard content.

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");
    }
}
开始看清了 2024-11-04 04:42:53

我认为这会起作用:)

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

}

I think this would work :)

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

}

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文