当前位置: 首页 > 面试题库 >

Java:使用剪贴板在同一应用程序的不同实例之间复制粘贴Java对象

卞成荫
2023-03-14
问题内容

我正在尝试在同一应用程序的不同实例之间实现对象的复制粘贴。当前,它仅在一个应用程序中起作用(我的意思是在同一应用程序实例中复制和粘贴),但在不同实例之间不起作用。

复制代码:

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

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

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

如果我从复制对象的同一应用程序实例中执行此操作,则它将起作用:flavors.lengthis
1,mimetype是application/x-java-serialized-object,并且很好。

但是,如果我打开应用程序,执行复制,然后再次打开同一应用程序(第一个未关闭,即两个实例同时运行),然后尝试从此处检查剪贴板内容,flavors.length则为0

我检查了文档和以下示例:一,二,但是我仍然找不到实现中的错误。

我错过了什么?

UPD: 我添加了sscce:剪贴板 _test.zip 。

这是具有3个源文件的测试应用程序(我使用Eclipse进行构建):

  • ClipboardTest.java -主要应用程式类别
  • MyObject.java -复制/粘贴对象的类(此类仅包含的数组String
  • MyObjectSelection.java -实现TranserableClipboardOwner接口的类

有两个按钮:“复制”,“测试”。

当您按下“复制”按钮时,将创建MyObject的新实例并将其放置到剪贴板中。

当您按下“测试”按钮时,剪贴板中的内容将被检查并回显到控制台(受支持DataFlavor的数量,以及每个DataFlavor

因此,重复这些步骤:

  • 开始申请

  • 按“复制”按钮:您将"object copied"在日志中看到消息

  • 按下“测试”按钮:您将看到剪贴板的内容:

       flavors.length = 1
    

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

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

  • 按下“测试”按钮:您将看到剪贴板为空:

       flavors.length = 0
    

这是为什么?

UPD2: sscce直接发布在这里:

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

     }

  }

问题答案:

引用本教程:

使用此机制传输数据使用Object序列化,因此用于传输数据的类必须实现该Serializable接口,以及与该序列化的所有对象也必须实现。如果所有内容都不可序列化,则您会看到一个NotSerializableException放置期间或复制到剪贴板的消息。

MyObject不是Serializable,因此无法正常工作。该框架显然可以检测到这一事实(与可序列化父类的不可序列化子类的情况相反,或者类似的情况是仅在流程中检测到不可序列化),因此它甚至不会为其他流程提供这种味道。

通常,同一Java应用程序的两个实例不会具有相同的地址空间,因此它们不能简单地访问彼此的内存。因此,您传输的所有内容都必须序列化。



 类似资料:
  • 问题内容: 当我尝试使用粘贴到单元格时,我要粘贴的单元格保持空白,但setValueAt()似乎可以正常工作。另外,当我尝试从一个单元格剪切或复制JPopupMenu时,如果要粘贴到另一个单元格,则我的“粘贴”选项将保持禁用状态。我不知道为什么。我的代码如下。 Here’s my code for 问题答案: 根据您的示例代码,并且必须填写空白,它对 我有用… Now, maybe you’d l

  • 使用“复制链接”按钮复制链接 导航到其他输入/文本字段 用Ctrl+V粘贴到字段中,并读取该字段的内容以验证 我的测试: 但是,没有任何内容粘贴到该输入(和return)。 谢了!

  • 问题内容: 我想从Java中的系统剪贴板中粘贴。我该怎么做? 问题答案: 尽管机器人类可以工作,但它不像直接使用系统剪贴板那样优雅,例如:

  • 问题是,从vim到剪贴板的复制/粘贴停止工作。我不知道为什么。。。 在中,我也没有看到和缓冲区... 这是我的。vimrc,如果需要的话。 有什么建议吗? 谢谢

  • 问题内容: 我正在寻找一个如何将文本复制到iOS剪贴板的干净示例,然后可以在其他应用程序中使用/粘贴该文本。 此功能的优点是可以快速复制文本,而无需传统文本复制的标准文本突出显示功能。 我假设键类在其中,但是在它们提供的代码示例中找不到相关的区域。 问题答案: 如果您只需要纯文本,则可以使用属性。它既可读又可写: (从剪贴板中 读取数据时 ,UIPasteboard文档还建议您首先检查一下,“以避

  • 在Linux上不接触鼠标,在命令模式下的VIM和系统剪贴板之间复制粘贴的最快方法是什么?