Java的:同一个应用程序的不同实例之间使用剪贴板复制粘贴的Java对象 [英] Java: use clipboard to copy-paste java objects between different instances of same application

查看:113
本文介绍了Java的:同一个应用程序的不同实例之间使用剪贴板复制粘贴的Java对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想实现同一应用程序的不同实例间的对象复制粘贴。目前,它只能在一个应用程序(我的意思是,复制和应用的相同实例粘贴),但不同的实例之间无法正常工作。

复制code:

  // MyObject来是一类我要复制/粘贴的对象;
// MyObjectSelection是impements转让的,ClipboardOwner接口的类剪贴板剪贴板= Toolkit.getDefaultToolkit()getSystemClipboard()。
为MyObject数据=新MyObject来(selectedItems);
MyObjectSelection dataSelection =新MyObjectSelection(数据);
clipboard.setContents(dataSelection,这一点);

在这之后,我可以检查剪贴板内容,这样的:

 剪贴板剪贴板= Toolkit.getDefaultToolkit()getSystemClipboard()。
转让clipboardContent = clipboard.getContents(本);的DataFlavor [] =口味clipboardContent.getTransferDataFlavors();
的System.out.println(flavors.length =+ flavors.length);
的for(int i = 0; I< flavors.length;我++){
   的System.out.println(味道=+香精[I]);
}

如果我这样做,从我复制的对象相同的应用程序实例,它的工作原理: flavors.length 1 ,MIME类型为应用程序/ x-j​​ava的序列化对象,那么,它的工作原理。

但是,如果我打开应用程序,执行复制,然后再次打开相同的应用程序(第一个是不封闭的,即两个实例同时运行),并尝试从那里检查剪贴板中的内容,那么 flavors.length 0

我检查了文档和这些例子: 之一,的,但我仍然找不到什么是错的,我的实现。

我错过了什么?


UPD:我加SSCCE: clipboard_test.zip

这是测试应用程序(我使用Eclipse来构建它)3源文件:


  • ClipboardTest.java - 主应用程序类

  • MyObject.java - 类对象进行复制/粘贴(该类包含字符串的只是数组)

  • MyObjectSelection.java - 类,它实现 Transerable ClipboardOwner 接口

    有两个按钮:复制,测试

    在preSS复制按钮,则会创建MyObject来的新实例
    并提出到剪贴板。

    在preSS测试按钮,剪贴板上的内容进行检查
    和呼应到控制台(计数支持的,并且每个的DataFlavor 的DataFlavor

    那么,复制下列步骤操作:


  • 启动应用程序


  • preSS复制按钮:在日志
  • 您会看到对象复制信息
  • preSS测试按钮:你会看到剪贴板中的内容:

      flavors.length = 1
       味[0] = java.awt.datatransfer.DataFlavor[mimetype=application/x-java-serialized-object;re$p$psentationclass=MyObject]


  • 启动应用程序的另一个实例(不要关闭第一个)


  • preSS测试按钮:你会看到剪贴板是空的:

      flavors.length = 0


这是为什么?


UPD2: SSCCE直接贴在这里:

 进口java.awt.BorderLayout中;  进口java.awt.datatransfer.Clipboard中;
  进口java.awt.datatransfer.ClipboardOwner;
  进口java.awt.datatransfer.DataFlavor中;
  进口java.awt.datatransfer.Transferable;
  进口java.awt.datatransfer.UnsupportedFlavorException;  进口java.awt.event.ActionEvent中;
  进口java.awt.event.ActionListener;  进口java.awt.Toolkit中;  进口javax.swing.JButton中;
  进口javax.swing.SwingUtilities中;
  进口javax.swing.JFrame中;  公共final类ClipboardTest实现Runnable,ClipboardOwner {     公共静态无效的主要(字串[] args){
        SwingUtilities.invokeLater(新ClipboardTest());
     }     公共无效的run(){        JFrame的F =新的JFrame(剪贴板测试);
        f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);        // - 创建复制按钮。
        //当你点击它,新对象test_items成为创建
        //并把到剪贴板。
        {
           JButton的button_copy =的新的JButton(拷贝);
           button_copy.addActionListener(新的ActionListener(){
              公共无效的actionPerformed(ActionEvent的五){                 的String [] = test_items {
                    一二三
                 };                 剪贴板剪贴板= Toolkit.getDefaultToolkit()getSystemClipboard()。
                 为MyObject数据=新MyObject来(test_items);
                 MyObjectSelection dataSelection =新MyObjectSelection(数据);
                 clipboard.setContents(dataSelection,ClipboardTest.this);                 的System.out.println(对象复制);
              }
           });
           f.add(button_copy,BorderLayout.NORTH);
        }        // - 创建测试按钮。
        //当你点击它,剪贴板上的内容进行检查
        //和呼应到控制台(支持的DataFlavor的计数,每个的DataFlavor)
        {
           JButton的button_test =的新的JButton(测试);
           button_test.addActionListener(新的ActionListener(){
              公共无效的actionPerformed(ActionEvent的五){                 剪贴板剪贴板= Toolkit.getDefaultToolkit()getSystemClipboard()。
                 转让clipboardContent = clipboard.getContents(本);                 的DataFlavor [] =口味clipboardContent.getTransferDataFlavors();
                 的System.out.println(flavors.length =+ flavors.length);
                 的for(int i = 0; I< flavors.length;我++){
                    的System.out.println(味道[+ I +] =+香精[I]);
                 }              }
           });
           f.add(button_test,BorderLayout.SOUTH);
        }        f.pack();
        f.setVisible(真);
     }     // ClipboardOwner实施     @覆盖
     公共无效lostOwnership(剪贴板剪贴板,可转让可转让){
        的System.out.println(ClipboardTest:失落的所有权);
     }     / * ************ *****************************************
      *我要复制的对象/粘贴
      * ******************* *************************************** /     公共静态类为MyObject {        私有String []项目;        公众为MyObject(字符串[]项){
           this.setItems(项目);
        }        公众的String [] getItems(){
           返回this.items;
        }        公共无效setItems(字符串[]项){
           this.items =物品;
        }     }
     公共静态类MyObjectSelection实现转换,ClipboardOwner {        私有静态的DataFlavor dmselFlavor =新的DataFlavor(MyObject.class,测试数据味);
        私人MyObject来选择;        公共MyObjectSelection(myObject的选择){
           this.selection =选择;
        }
        //转换的实现        @覆盖
        公众的DataFlavor []而getTransferDataFlavors(){
           的System.out.println(而getTransferDataFlavors);
           的DataFlavor [] = RET {dmselFlavor};
           返回RET;
        }        @覆盖
        公共布尔isDataFlavorSupported方法(DataFlavor的味道){
           返回dmselFlavor.equals(风味);
        }        @覆盖
        公共同步对象getTransferData(DataFlavor的味道)
           抛出UnsupportedFlavorException
        {
           如果(isDataFlavorSupported方法(味)){
              返回this.selection;
           }其他{
              抛出新UnsupportedFlavorException(dmselFlavor);
           }
        }        // ClipboardOwner实施        @覆盖
        公共无效lostOwnership(剪贴板剪贴板,可转让可转让){
           的System.out.println(MyObjectSelection:失落的所有权);
        }     }  }


解决方案

引用的本教程


  

使用此机制使用对象串行传输数据,因此该类用来传送数据必须实现序列化接口,必须任何序列化它。如果一切都没有序列化,你会下降过程中看到一个 NotSerializableException 或者复制到剪贴板。


为MyObject 不是的 序列化 ,所以它不能正常工作。框架显然检测该事实(而不是一情况与序列化父类,或仅检测到在这个过程中的非串行化相似的场景的一个不可序列化亚类),因此它甚至不会提供该风味其他进程。

在一般情况下,同一个Java应用的两个实例将不会有相同的地址空间,所以它们不能简单地访问彼此的存储器。因此,您传递一切都被序列化。

I am trying to implement copy-paste of objects between different instances of same application. Currently it works only in one application (I mean, copy and paste in the same instance of application), but does not work between different instances.

Copying code:

// MyObject is a class of objects I want to copy/paste;
// MyObjectSelection is a class that impements Transferable and ClipboardOwner interfaces

Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
MyObject data = new MyObject(selectedItems);
MyObjectSelection dataSelection = new MyObjectSelection(data);
clipboard.setContents(dataSelection, this);

After that, I can check contents of the clipboard, like that:

Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
Transferable clipboardContent = clipboard.getContents(this);

DataFlavor[] flavors = clipboardContent.getTransferDataFlavors();
System.out.println("flavors.length=" + flavors.length);
for (int i = 0; i < flavors.length; i++){
   System.out.println("flavor=" + flavors[i]);
}

If I do this from the same application instance that I copied object, it works: flavors.length is 1, mimetype is application/x-java-serialized-object, and, well, it works.

But if I open application, perform copy, then open the same application again (first one isn't closed, i.e. both instances are running simultaneously), and try to check clipboard contents from there, then flavors.length is 0.

I examined the docs and these examples: one, two, but I still can't find what is wrong in my implementation.

Did I miss something?


UPD: I added sscce: clipboard_test.zip.

This is test application (I use Eclipse to build it) with 3 source files:

  • ClipboardTest.java - main app class
  • MyObject.java - class for objects to copy/paste (this class contains just array of String)
  • MyObjectSelection.java - class that implements Transerable and ClipboardOwner interfaces

    There are two buttons: "copy", "test".

    When you press "copy" button, new instance of MyObject is created and put to the clipboard.

    When you press "test" button, clipboard contents are checked and echoed to the console (count of supported DataFlavor's, and each DataFlavor)

    So, replicate these steps:

  • Start application

  • Press "copy" button: you will see "object copied" message in the log
  • Press "test" button: you will see clipboard's contents:

       flavors.length = 1
       flavor[0] = java.awt.datatransfer.DataFlavor[mimetype=application/x-java-serialized-object;representationclass=MyObject]
    

  • Start another instance of the application (don't close the first one)

  • Press "test" button: you will see that clipboard is empty:

       flavors.length = 0
    

Why is that?


UPD2: sscce posted directly here:

  import java.awt.BorderLayout;

  import java.awt.datatransfer.Clipboard;
  import java.awt.datatransfer.ClipboardOwner;
  import java.awt.datatransfer.DataFlavor;
  import java.awt.datatransfer.Transferable;
  import java.awt.datatransfer.UnsupportedFlavorException;

  import java.awt.event.ActionEvent;
  import java.awt.event.ActionListener;

  import java.awt.Toolkit;

  import javax.swing.JButton;
  import javax.swing.SwingUtilities; 
  import javax.swing.JFrame;

  public final class ClipboardTest implements Runnable, ClipboardOwner {

     public static void main(String[] args) {
        SwingUtilities.invokeLater (new ClipboardTest());
     } 

     public void run() {

        JFrame f = new JFrame ("Clipboard test");
        f.setDefaultCloseOperation (JFrame.DISPOSE_ON_CLOSE);

        //-- Create "copy" button.
        //   When you click it, new object "test_items" becomes created
        //   and put to the clipboard.
        {
           JButton button_copy = new JButton("copy");
           button_copy.addActionListener(new ActionListener(){
              public void actionPerformed(ActionEvent e){

                 String[] test_items = {
                    "one", "two", "three"
                 };

                 Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
                 MyObject data = new MyObject(test_items);
                 MyObjectSelection dataSelection = new MyObjectSelection(data);
                 clipboard.setContents(dataSelection, ClipboardTest.this);

                 System.out.println("object copied");
              }
           });
           f.add(button_copy, BorderLayout.NORTH);
        }

        //-- Create "test" button.
        //   When you click it, clipboard contents are checked
        //   and echoed to the console (count of supported DataFlavor's, and each DataFlavor)
        {
           JButton button_test = new JButton("test");
           button_test.addActionListener(new ActionListener(){
              public void actionPerformed(ActionEvent e){

                 Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
                 Transferable clipboardContent = clipboard.getContents(this);

                 DataFlavor[] flavors = clipboardContent.getTransferDataFlavors();
                 System.out.println("flavors.length = " + flavors.length);
                 for (int i = 0; i < flavors.length; i++){
                    System.out.println("flavor[" + i + "] = " + flavors[i]);
                 }

              }
           });
           f.add(button_test, BorderLayout.SOUTH);
        }

        f.pack();
        f.setVisible(true);
     }



     // ClipboardOwner implementation

     @Override
     public void lostOwnership(Clipboard clipboard, Transferable transferable){
        System.out.println("ClipboardTest: Lost ownership");
     }







     /* *****************************************************************************************
      * Object that I want to copy/paste
      * ****************************************************************************************/

     public static class MyObject {

        private String[] items;

        public MyObject(String[] items){
           this.setItems(items);
        }

        public String[] getItems(){
           return this.items;
        }

        public void setItems(String[] items){
           this.items = items;
        }

     }




     public static class MyObjectSelection implements Transferable, ClipboardOwner {

        private static DataFlavor dmselFlavor = new DataFlavor(MyObject.class, "Test data flavor");
        private MyObject selection;



        public MyObjectSelection(MyObject selection){
           this.selection = selection;
        }


        // Transferable implementation

        @Override
        public DataFlavor[] getTransferDataFlavors(){
           System.out.println("getTransferDataFlavors");
           DataFlavor[] ret = {dmselFlavor};
           return ret;
        }

        @Override
        public boolean isDataFlavorSupported(DataFlavor flavor){
           return dmselFlavor.equals(flavor);
        }

        @Override
        public synchronized Object getTransferData (DataFlavor flavor)
           throws UnsupportedFlavorException 
        {
           if (isDataFlavorSupported(flavor)){
              return this.selection;
           } else {
              throw new UnsupportedFlavorException(dmselFlavor);
           }
        }



        // ClipboardOwner implementation

        @Override
        public void lostOwnership(Clipboard clipboard, Transferable transferable){
           System.out.println("MyObjectSelection: Lost ownership");
        }

     }

  }

解决方案

Quoting this tutorial:

Transferring the data using this mechanism uses Object serialization, so the class you use to transfer the data must implement the Serializable interface, as must anything that is serialized with it. If everything is not serializable, you will see a NotSerializableException during drop or copy to the clipboard.

Your MyObject is not Serializable, so it cannot work. The framework apparently detects this fact (as opposed to a situation with an unserializable subclass of a serializable parent class, or similar scenarios where non-serializability is detected only in the process), so it won't even offer that flavor to other processes.

In general, two instances of the same java application won't have the same address space, so they can't simply access one another's memory. Therefore everything you transfer has to be serialized.

这篇关于Java的:同一个应用程序的不同实例之间使用剪贴板复制粘贴的Java对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆