Сценарий
Я использую FlavorListener для переключения кнопки при изменении типа содержимого буфера обмена. Прослушиватель вызывает Clipboard#getAvailableDataFlavors, что приводит к непоследовательному выдаче исключения при копировании данных из других программ:
Код: Выделить всё
Exception in thread "AWT-EventQueue-0" java.lang.IllegalStateException: cannot open system clipboard
at sun.awt.windows.WClipboard.openClipboard(Native Method)
at sun.awt.datatransfer.SunClipboard.getClipboardFormatsOpenClose(SunClipboard.java:327)
at sun.awt.datatransfer.SunClipboard.getAvailableDataFlavors(SunClipboard.java:168)
Чтобы воспроизвести проблему, запустите приведенную ниже программу и скопируйте данные в системный буфер обмена из другой программы (вам может потребоваться несколько попыток копирования, прежде чем будет создано исключение):
Код: Выделить всё
import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.FlavorListener;
import java.util.Arrays;
import java.util.Scanner;
public class Foo {
public static void main(String[] args) {
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
FlavorListener listener = e -> System.out.print("\rClipboard has text: "
+ Arrays.stream(clipboard.getAvailableDataFlavors()).anyMatch(DataFlavor::isFlavorTextType)
+ "\nPress enter to exit...");
clipboard.addFlavorListener(listener);
System.out.print("Press enter to exit...");
new Scanner(System.in).nextLine();
}
}
Внутренне буфер обмена AWT использует функцию OpenClipboard из winuser.h. Согласно документации, «OpenClipboard завершается с ошибкой, если в другом окне открыт буфер обмена». Глядя на базовый код C++ для буфера обмена AWT, мы видим, что это именно причина исключения IllegalStateException.
При исследовании этого вопроса я нашел похожие вопросы:
- В Java почему я получаю исключение java.lang.IllegalStateException: невозможно открыть системный буфер обмена
- слушать изменения в буфере обмена, проверка владения?
Возражения
Я предпочитаю не полагаться на сон, потому что нет возможности узнать это с помощью уверенность, когда (или если!) буфер обмена будет закрыт. Дополнительно:
- Если вы не спите достаточно долго, IllegalStateException все равно будет возникать.
- Продолжительность сна, которая работает на одном компьютере, не гарантирует, что она будет работать на другом компьютере.
- Продолжительность сна, которая успешно ожидает закрытия буфера обмена одним приложением, не обязательно будет работать для другого.
- Если вы «соблюдаете осторожность» и используете очень длительную продолжительность сна:
- Пользователю, возможно, придется дождаться включения кнопки.
- Пользователь может нажать кнопку, прежде чем она будет отключена (что приведет к возникновению ошибки).
- Сон на Поток событий AWT заморозит пользовательский интерфейс, не позволяя пользователю выполнять другие действия, не зависящие от буфера обмена.
- Мне пришлось бы использовать больше системных ресурсов для создания рабочего потока только для выполнения спящего режима.
Я хотел бы узнать, есть ли прослушиватель или обратный вызов, который можно зарегистрировать для выполнения, когда буфер обмена закрыт. Существует ли что-нибудь подобное?
Чтобы уточнить, я открыт для возможности написания моей собственной общей/динамически подключаемой библиотеки, если мне нужно использовать встроенную функцию для достижения этой цели.
Подробнее здесь: https://stackoverflow.com/questions/790 ... een-closed
Мобильная версия