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(使用前将#替换为@)