Я пишу небольшую Java-программу, которая должна запускать внешнюю программу, которая копирует изображение в системный буфер обмена (т. Е. Windows 7 «инструмент обрезки»), дождаться его завершения, сохранить изображение из буфера обмена в диск и скопировать URL (с которого изображение может быть доступно) в буфер обмена. Короче говоря, предполагается:
- запустить внешний инструмент и дождаться его
- скопировать изображение из буфера обмена
- скопировать строку в буфер обмена
Это моя программа прекрасно умеет делать. Тем не менее, я хотел бы использовать Swing / AWT для представления пользовательского интерфейса. Я использую значок в системном трее, но для простоты, это может быть JButton в кадре. Когда кнопка нажата, процесс выше должен быть выполнен. В первый раз, когда это сделано, все работает как надо. Изображение копируется, вставляется на диск, а строка копируется в буфер обмена. Затем, во время второго нажатия кнопки, как будто моя программа не понимает, что буфер обмена был обновлен, поскольку он все еще видит свою собственную строку с первого раза. Только после этого мой класс обработки буфера обмена теряет владение, и фактически каждая вторая попытка выполнения этой процедуры завершается неудачей.
import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.ClipboardOwner;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.StringSelection;
import java.awt.datatransfer.Transferable;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.swing.JButton;
import javax.swing.JFrame;
public class Main {
private static BufferedImage image; //the image from clipboard to be saved
public static void main(String[] args) throws InterruptedException, IOException {
new GUI();
}
public static void run(String filename) throws IOException, InterruptedException {
CBHandler cbh = new CBHandler();
//run tool, tool will copy an image to system clipboard
Process p = Runtime.getRuntime().exec("C:\\Windows\\system32\\SnippingTool.exe");
p.waitFor();
//copy image from clipboard
image = cbh.getClipboard();
if(image == null) {
System.out.println("No image found in clipboard.");
return;
}
//save image to disk...
//copy file link to clipboard
String link = "http://somedomain.com/" + filename;
cbh.setClipboard(link);
}
}
class CBHandler implements ClipboardOwner {
public BufferedImage getClipboard() {
Transferable t = Toolkit.getDefaultToolkit().getSystemClipboard().getContents(null);
try {
if(t.isDataFlavorSupported(DataFlavor.imageFlavor))
return (BufferedImage) t.getTransferData(DataFlavor.imageFlavor);
}
catch(Exception e) {
e.printStackTrace();
}
return null;
}
public void setClipboard(String str) {
StringSelection strsel = new StringSelection(str);
Toolkit.getDefaultToolkit().getSystemClipboard().setContents(strsel, this);
}
@Override
public void lostOwnership(Clipboard arg0, Transferable arg1) {
System.out.println("Lost ownership!");
}
}
class GUI extends JFrame {
public GUI() {
JButton button = new JButton("Run");
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
try {
Main.run("saveFile.png");
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
add(button);
pack();
setVisible(true);
}
}
Если вы попытаетесь запустить его, обратите внимание, что при втором запуске метод lostOwnership вызывается только ПОСЛЕ попытки копирования изображения. Я предполагаю, что это источник моей проблемы, и я понятия не имею, почему это происходит, за исключением того, что это происходит только при запуске события Swing. Любая помощь в решении этой проблемы приветствуется.