10

クリップボードの内容を表示する小さなデスクトップ アプリを作成しようとしています (文字列の場合)。私はそれを行うコンストラクターを作成しましたが、うまく機能します。テキストが OS のクリップボードにコピーされるたびに、同様のメソッドを呼び出したいだけです。私はこれにかなり慣れていないので、どんな助けでも大歓迎です!なんらかの方法で割り込みを使用する必要があると何かが教えてくれます...

package pasty;

import java.awt.FlowLayout;
import java.awt.Toolkit;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextField;

public class PastyFrame implements KeyListener {

    String currentClipboardString;
    JLabel clipboardLabel = new JLabel();

    public PastyFrame() {
        JFrame frame = new JFrame();
        frame.setVisible(true);

        try {
            currentClipboardString = (String) Toolkit.getDefaultToolkit().getSystemClipboard().getData(DataFlavor.stringFlavor);
        } catch (UnsupportedFlavorException | IOException ex) {
            Logger.getLogger(PastyFrame.class.getName()).log(Level.SEVERE, null, ex);

            currentClipboardString = "";
        }
        if (currentClipboardString.isEmpty()) {
            currentClipboardString = "The clipboard is empty";
        }
        frame.setSize(400, 100);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setResizable(false);
        frame.setLayout(new FlowLayout());


        clipboardLabel.setText(currentClipboardString);
        frame.add(clipboardLabel);
}
4

7 に答える 7

13

Clipboard.addFlavorListenerを呼び出して、OS からのクリップボードの更新をリッスンできます。

Toolkit.getDefaultToolkit().getSystemClipboard().addFlavorListener(new FlavorListener() { 
   @Override 
   public void flavorsChanged(FlavorEvent e) {

      System.out.println("ClipBoard UPDATED: " + e.getSource() + " " + e.toString());
   } 
}); 

いくつかの補足事項:

  • アプリケーションを起動するには、初期スレッドの使用を検討してください。
  • JFrame.packフレーム サイズを設定するために呼び出します。
  • SwingKeyListenersでのマッピングには、キー バインドが優先されます。KeyEvents
于 2013-01-09T00:07:15.653 に答える
11

私はこれを使います。クラス全体。

public class ClipBoardListener extends Thread implements ClipboardOwner{
Clipboard sysClip = Toolkit.getDefaultToolkit().getSystemClipboard();  


    @Override
  public void run() {
    Transferable trans = sysClip.getContents(this);  
    TakeOwnership(trans);       

  }  

    @Override
  public void lostOwnership(Clipboard c, Transferable t) {  

  try {  
    ClipBoardListener.sleep(250);  //waiting e.g for loading huge elements like word's etc.
  } catch(Exception e) {  
    System.out.println("Exception: " + e);  
  }  
  Transferable contents = sysClip.getContents(this);  
    try {
        process_clipboard(contents, c);
    } catch (Exception ex) {
        Logger.getLogger(ClipBoardListener.class.getName()).log(Level.SEVERE, null, ex);
    }
  TakeOwnership(contents);


}  

  void TakeOwnership(Transferable t) {  
    sysClip.setContents(t, this);  
  }  

public void process_clipboard(Transferable t, Clipboard c) { //your implementation
    String tempText;
    Transferable trans = t;

    try {
        if (trans != null?trans.isDataFlavorSupported(DataFlavor.stringFlavor):false) {
            tempText = (String) trans.getTransferData(DataFlavor.stringFlavor);
            System.out.println(tempText);  
        }

    } catch (Exception e) {
    }
}

}

他のプログラムがクリップボードの所有権を取得すると、250 ミリ秒待機し、更新されたコンテンツでクリップボードの所有権を取り戻します。

于 2013-01-09T00:29:09.803 に答える
2

この問題に対する別の解決策を思いつきました。次のリスナーは、ループを使用してクリップボードの内容を継続的に読み取ります。テキストが検出されると、キャッシュされたクリップボードの以前のコンテンツと比較されます。以前にキャッシュされていない新しいテキストがクリップボードに含まれている場合、この例のように「オブザーバーに通知する」などのアクションを実行し、GUI 自体を更新するように促す場合があります。

この例では、クリップボードに文字列以外のものが含まれているコンテンツの変更は無視されます。

コンテンツ タイプの変更を検出する (つまり、FlavorListerner を使用する) だけでなく、このソリューションは継続的な文字列比較によって変更を検出します。クリップボードに読み取りアクセスするだけで、たとえばクリップボードの所有権を取得するよりも、このコードが他のアプリケーションに干渉することが少なくなると思います。

提案は大歓迎です。

package gui;

import java.awt.HeadlessException;
import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.Observable;

/**
 * @author Matthias Hinz
 */
class ClipboardTextListener extends Observable implements Runnable {

    Clipboard sysClip = Toolkit.getDefaultToolkit().getSystemClipboard();

    private volatile boolean running = true;

    public void terminate() {
        running = false;
    }

    public void run() {
        System.out.println("Listening to clipboard...");
        // the first output will be when a non-empty text is detected
        String recentContent = "";
        // continuously perform read from clipboard
        while (running) {
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            try {
                // request what kind of data-flavor is supported
                List<DataFlavor> flavors = Arrays.asList(sysClip.getAvailableDataFlavors());
                // this implementation only supports string-flavor
                if (flavors.contains(DataFlavor.stringFlavor)) {
                    String data = (String) sysClip.getData(DataFlavor.stringFlavor);
                    if (!data.equals(recentContent)) {
                        recentContent = data;
                        // Do whatever you want to do when a clipboard change was detected, e.g.:
                        System.out.println("New clipboard text detected: " + data);
                        setChanged();
                        notifyObservers(data);
                    }
                }

            } catch (HeadlessException e1) {
                e1.printStackTrace();
            } catch (UnsupportedFlavorException e1) {
                e1.printStackTrace();
            } catch (IOException e1) {
                e1.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        ClipboardTextListener b = new ClipboardTextListener();
        Thread thread = new Thread(b);
        thread.start();
    }
}
于 2018-09-29T20:41:33.127 に答える
1

以下はSSCCEです...実行してテキストを選択し、Ctrl-Cを複数回押すことができます...選択したテキストが印刷されます。

ご覧のとおり、Reimius の回答よりも少し複雑です。実際には、新しいテキストをコピーするたびにフレーバー リスナーが応答するようにするには、クリップボードをクリアする必要があります (これはトリッキーです!)。

さらに、クリップボードをクリアするときに「フレーバーの変化」によって引き起こされる出力を抑制する必要があるかもしれませんが、私よりも賢い解決策があるかもしれません。

public class ClipboardListenerTest {

    public static void main(String[] args) throws InvocationTargetException, InterruptedException {

        SwingUtilities.invokeAndWait(new Runnable() {
            public void run() {
                final Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
                clipboard.addFlavorListener(new FlavorListener() {
                    // this is needed to prevent output when you clear the clipboard
                    boolean suppressOutput = false;

                    // this is a specially devised Transferable - sole purpose to clear the clipboard
                    Transferable clearingTransferable = new Transferable() {
                        public DataFlavor[] getTransferDataFlavors() {
                            return new DataFlavor[0];
                        }
                        public boolean isDataFlavorSupported(DataFlavor flavor) {
                            return false;
                        }
                        public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException {
                            throw new UnsupportedFlavorException(flavor);
                        }
                    };

                    @Override
                    public void flavorsChanged(FlavorEvent e) {
                        Transferable contentsTransferable = clipboard.getContents(null);
                        // NB the Transferable returned from getContents is NEVER the same as the 
                        // clearing Transferable!

                        if (!suppressOutput) {
                            System.out.println(String.format("# clipboard UPDATED, src %s, string %s, clearingT? %b", e.getSource(), e.toString(),
                                    contentsTransferable == clearingTransferable));
                            try {
                                String stringData = (String)clipboard.getData(DataFlavor.stringFlavor);
                                System.out.println(String.format("# string data |%s|", stringData ));
                            } catch (UnsupportedFlavorException | IOException e1) {
                                // TODO Auto-generated catch block
                                e1.printStackTrace();
                            } 
                        }

                        else {
                            // my experiments seem to show that you have to spawn a new Runnable if you want 
                            // to leave suppressOutput long enough for it to prevent the "CLEAR" operation 
                            // producing output...
                            SwingUtilities.invokeLater(new Runnable() {
                                @Override
                                public void run() {
                                    suppressOutput = false;
                                }
                            });

                        }
                        suppressOutput = true;
                        clipboard.setContents(clearingTransferable, null);
                    }
                });

            }

        });

        int i = 0;
        while (i < 100) {
            Thread.sleep(500L);
            System.out.println("# pibble");
            i++;
        }

    }

}
于 2016-05-30T14:55:32.707 に答える