如果不是 SwingUtilities.invokeLater(),Java 剪贴板将忽略用户副本

2023-12-23

Problem:以编程方式在 Java 中设置剪贴板内容,然后获取剪贴板文本永远不会反映手动剪贴板内容更改。但是,推迟通过 SwingUtilities.invokeLater() 获取剪贴板文本直到处理完所有 Swing 事件确实反映了当前和以后的手动剪贴板内容更改。以编程方式设置剪贴板内容再次返回到损坏的行为。

问题:为什么是这样?这是 Java 错误/未记录且有意为之吗?

再生产:更改为 Swing 线程。按程序设置剪贴板内容。反复打印剪贴板内容,验证用户手动复制操作没有被反映。再次重复打印,但通过额外的 SwingUtilities.invokeLater() 调用推迟此操作。下面的代码连续两次执行所有这些操作。

Windows Java 版本:
微软Windows [版本10.0.14393]
java版本“1.8.0_74”
Java(TM) SE 运行时环境(版本 1.8.0_74-b02)
Java HotSpot(TM) 64 位服务器 VM(内部版本 25.74-b02,混合模式)

(
W&J 版本是 2017 年 1 月,当时我发表了这篇文章。
2017 年 9 月,Java 中仍然存在该错误。
微软Windows [版本10.0.15063]
java版本“1.8.0_144”
Java(TM) SE 运行时环境(版本 1.8.0_144-b01)
Java HotSpot(TM) 64 位服务器 VM(内部版本 25.144-b01,混合模式)
)

SSCCE:

package com.potentialjavabug;

import javax.swing.*;
import java.awt.*;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.StringSelection;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.IOException;
import java.util.Arrays;

final public class OMFGClipboardProblems {

    final private static int PRINTLOOPCOUNT = 10;

    public static void main(final String[] args) {


        SwingUtilities.invokeLater(() -> {


            printClipboardContent();


            pause();
            pause();
            System.err.println("You just saw the clipboard content this program started with. Now follows a loop with programmatically set clipboard text.");
            pause();
            pause();


            setClipboardText("Try to copy text anywhere in your system to the clipboard while this loop runs " + PRINTLOOPCOUNT + " times. You will see that this is ignored!");
            printClipboardContentAFewTimes();
            setClipboardText("And programmatically setting the clipboard still works.");
            printClipboardContent();


            pause();
            pause();
            System.err.println("\n\n\n\nOk, now let's do this again: I'm NOT gonna set the clipboard text like I did before, and I will print out the current clipboard content just like before. But I'm gonna do it after all currently pending Swing events have been processed! You will notice that your copy actions DO have effect now.");
            pause();
            pause();


            SwingUtilities.invokeLater(() -> {


                printClipboardContentAFewTimes();


                pause();
                pause();
                setClipboardText("THIS IS NEW text set programmatically. Try to copy any other text to the clipboard. You'll see that it again does not work.");
                printClipboardContentAFewTimes();
                pause();
                pause();


                System.err.println("\n\n\n\nAnd now, the SwingUtilities.invokeLater trick again. Try to copy, and you'll see that this text indeed changes.");
                pause();
                pause();


                SwingUtilities.invokeLater(OMFGClipboardProblems::printClipboardContentAFewTimes);

            });

        });


    }


    private static void printClipboardContentAFewTimes() {

        for (int i = 0; i < PRINTLOOPCOUNT; i++) {
            pause();
            printClipboardContent();
        }
    }


    private static void printClipboardContent() {

        System.err.print("\nCURRENT CLIPBOARD CONTENT:");
        System.err.println(getClipboardText());
    }


    private static void pause() {

        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }


    private static void setClipboardText(final String text) {

        final Clipboard c = Toolkit.getDefaultToolkit().getSystemClipboard();
        final StringSelection data = new StringSelection(text);
        c.setContents(data, data);
    }


    private static String getClipboardText() {

        final Clipboard c = Toolkit.getDefaultToolkit().getSystemClipboard();
        final DataFlavor[] availableDataFlavors = c.getAvailableDataFlavors();

        final String flavorPrefixString = "***DATA FLAVORS: " + Arrays.toString(availableDataFlavors) + "***\n";

        if (!c.isDataFlavorAvailable(DataFlavor.stringFlavor)) {
            return flavorPrefixString;
        }
        try {
            final Object data = c.getData(DataFlavor.stringFlavor);
            final String ret = (String) data;
            return flavorPrefixString + ret;
        } catch (UnsupportedFlavorException | IOException ex) {
            ex.printStackTrace(); // Shouldn't happen since we explicitly checked.
        }
        return "error";
    }


}

None

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如果不是 SwingUtilities.invokeLater(),Java 剪贴板将忽略用户副本 的相关文章

随机推荐

  • 使用 OraclePreparedStatement 通过 Tomcat 8.5.9 从 java 8 写入 oracle 11.2 数据库?

    我在使用 Java 8 和 Tomcat 8 5 9 写入 Oracle 11 2 数据库时遇到问题 实际上 以下代码对于写入存储过程来说效果很好 但是在直接写入数据库时 出现错误 Context initCtx new InitialCo
  • 以编程方式安装 .mobileconfig

    我正在编写一个应用程序 以便自动执行将 Apple 移动设备连接到 WiFi 网络并将配置文件下载到设备的过程 由于它是自动化的 通过 Native Driver 等 因此所有功能都需要由应用程序本身控制 而不是发送到其他应用程序 例如 设
  • 如何将 pandas 数据分组推广到 3 个以上的维度?

    我正在使用优秀的pandas包来处理大量不同的气象诊断数据 当我将数据拼接在一起时 我很快就耗尽了维度 查看文档 可能是使用MultiIndex可能会解决我的问题 但我不确定如何将其应用到我的情况 文档显示了使用随机数据创建 MultiIn
  • 在 WinForms 应用程序中嵌入 Word 文档预览

    如何像资源管理器预览面板一样将 Word 文档嵌入到表单或用户控件中 I found 这个话题 http social msdn microsoft com Forums en csharpgeneral thread 127bd801 5
  • 如何在android studio 3.1.2中通过gradle安装geotools

    我想在我的项目中使用 geotools 所以我在我的存储库项目 gradle 中添加了 geotools lib allprojects repositories maven url http repo boundlessgeo com m
  • 在 Svelte 的 main.js 中导入本地 json

    将 JSON 导入 Svelte 的 main js 文件的模式是什么 我想 import App from App html const dataset require posts json console log dataset con
  • 面向 .NET Core 3.1 的 C++/CLI

    NET Core 3 1 添加了对 C CLI 的支持 宣布 NET Core 3 1 https devblogs microsoft com dotnet announcing net core 3 1 官方公告列出了两个新的项目模板
  • .NET Windows 服务 - 架构决策

    我目前有一个全天持续运行的 Windows 服务 它有多个启动线程 每天更新缓存的任务 每周任务进行清理 将 XML 导入 SQL Server 的 24 7 任务 每天运行大约 12 小时的任务 启动控制台应用程序来管理 ETL 这些任务
  • 在 Java8 中设置 LocalDateTime 和时区的格式

    我有这个简单的代码 DateTimeFormatter FORMATTER DateTimeFormatter ofPattern yyyyMMdd HH mm ss SSSSSS Z LocalDateTime now format FO
  • 视图中的 HttpContext.User 或 Page.User?

    如果我在 Asp net MVC 的视图中编码并且我想获取当前用户 那么使用是否更好 Page User or HttpContext User 有区别吗 Page User回报this Context User这与HttpContext
  • ChromeDriver 控制台应用程序隐藏

    我创建了一个播放器 它将使用 C 中的 selenium 和 ChromeDriver 来自动化 chrome 运行良好 我面临的问题是 当它为 ChromDriver 创建对象时 它将启动 ChromeDriver 应用程序 该应用程序会
  • 反应事件未触发

    在与 img 标签并熟悉 React 我发现我的onLoad and onError事件没有触发 在将我的使用简化为最基本的 React 组件之后 我仍然发现事件没有触发 在下面的组件中 我希望单击渲染的 div 登录到控制台 它渲染得很好
  • Woocommerce - 产品页面中的描述

    我需要在 Woocommerce 插件中添加我的 产品 描述的一些摘录 我有这样的页面 http exploreprague cz guides buddies 2 http exploreprague cz guides buddies
  • 用户使用 Azure AD 身份验证登录后调用适用于 Teams 的图形 API

    在用户使用 Azure AD 登录应用程序后 我们尝试使用 Microsoft Graph API for Teams 用户应该能够向应用程序内的 Teams 频道发送消息 我试图得到访问令牌登录用户并将其作为不记名令牌传递给图形 API
  • 如何使用 transclude 将 ngRepeat“模板”传递给 ngDirective?

    Demo http plnkr co edit TiH96FCgOGnXV0suFyJA p preview http plnkr co edit TiH96FCgOGnXV0suFyJA p preview 我有一个名为 myDirect
  • 避免壁纸横跨 5 个屏幕

    我一直面临一个问题 如何在 Android 中设置壁纸 而不将其拉伸到 5 个主屏幕 需要明确的是 我有一个分辨率为 320x480px 的资源图像 当我在 Android 中将其设置为壁纸时 它会拉伸到 5 个屏幕 但我希望它仅显示在 1
  • 不允许 > 2mb 的图像

    你好 如何检查用户是否尝试上传大于 2mb 的文件 我想否认这一点 并向尝试这样做的用户发出错误消息 我知道是这样的 但是我该如何将 50000 更改为 2mb 呢 if FILES imagefile size gt 50000 die
  • 为什么使用片段?

    我已阅读文档并其他一些问题的主题 https softwareengineering stackexchange com q 200583 127226对于这个话题 我并没有真正被说服 我不清楚使用这种技术的局限性 碎片现在被视为最佳实践
  • 如何使用 mongodb 和 php 正确处理分页查询?

    我这样做对吗 我查看了一些使用 MySQL 的旧 PHP 代码 并设法让它工作 但是我想知道是否有一种更 干净 和 更快 的方法来完成此任务 首先我需要获取 文档 的总数 total documents collection gt find
  • 如果不是 SwingUtilities.invokeLater(),Java 剪贴板将忽略用户副本

    Problem 以编程方式在 Java 中设置剪贴板内容 然后获取剪贴板文本永远不会反映手动剪贴板内容更改 但是 推迟通过 SwingUtilities invokeLater 获取剪贴板文本直到处理完所有 Swing 事件确实反映了当前和