A DESCRIPTION OF THE PROBLEM :
**The Problem**
JavaFX's default way of getting an image from the Windows clipboard, `Clipboard.getSystemClipboard().getImage();`, appears to be broken.
Something seems to go wrong with the transparency of the image. Set on a black background, the image appears fine, but set on a white background, nothing shows at all.
Here's an animation demonstrating that: https://i.stack.imgur.com/TgszF.gif
The provided source code allows easy comparison between the JavaFX and AWT clipboards.
**What I Know**
This problem with images doesn't occur on the AWT clipboard, just the JavaFX clipboard.
*Problem Applications*
JavaFX seems to have this same transparency problem with various applications that copy an image to the clipboard:
Adobe Reader (from a PDF with images)
Foxit Reader (from a PDF with images)
Here's a pdf with an image, for your convenience: https://drive.google.com/file/d/1waZRrQM6VTN1YzaVSHkxDIzV456Jqi0y/view?usp=sharing
Microsoft Word 365 (from a .docx file with images)
Here's a .docx file with an image, for your convenience: https://drive.google.com/file/d/1s3anuuIXZ4NcJGAbpYakwgqH_YAGPo9x/view?usp=sharing
Windows 7's Paint (.png, .jpg, .gif, .bmp)
Greenshot (which is an enhanced screenshot utility)
Firefox 65.0.2 (copying the Google.com logo)
*Applications Without The Issue*
I've also found a few applications that copy an image to the clipboard and JavaFX can pull it out using the default method no problem:
Paint.net
The PrtScn button
The Windows Snipping Tool
Google Chrome 72.0.3626.121 (copying the Google.com logo)
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. Copy an image from practically any application
[I've been able to replicate this problem with the following applications:
Adobe Reader (from a PDF with images)
Foxit Reader (from a PDF with images)
Microsoft Word 365 (from a .docx file with images)
Windows 7's Paint (.png, .jpg, .gif, .bmp)
Greenshot (which is an enhanced screenshot utility)
Firefox 65.0.2 (copying the Google.com logo)
]
2. Try to create and display an Image from the image copied to the JavaFX Clipboard.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
An image that maintains the same properties as the image that was copied
ACTUAL -
When displayed over something black, the image appears fine, when displayed over something white, no color shows. When displayed on a color in between, various colors do not display correctly, if at all.
Here's an animation of the actual result on numerous backgrounds, using a TV color testing graphic: https://i.stack.imgur.com/TgszF.gif
---------- BEGIN SOURCE ----------
// Instructions: This program allows you to easily compare the JavaFX and the Swing/AWT clipboard.
// First copy an image from some application.
// JavaFX button -> paste the image from the JavaFX clipboard.
// AWT button -> paste the image from the AWT clipboard.
// Use the color changer at the top to see how the image changes based on background that
// the image is displayed on.
package sample;
import com.sun.glass.ui.ClipboardAssistance;
import javafx.application.Application;
import javafx.embed.swing.SwingFXUtils;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.Button;
import javafx.scene.control.ColorPicker;
import javafx.scene.control.Label;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.Clipboard;
import javafx.scene.layout.Background;
import javafx.scene.layout.BackgroundFill;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.CornerRadii;
import javafx.stage.Stage;
import java.awt.*;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.IOException;
/**
* A program to test out the differences between the AWT Java Clipboard and the JavaFX Clipboard.
* <p>
* Based on the code by crusam: https://stackoverflow.com/q/48932575/5432315
*/
public class ClipBoardFxAwtComparison extends Application {
@Override
public void start(final Stage primaryStage) {
final BorderPane root = new BorderPane();
final ImageView view = new ImageView();
final Button awtButton = new Button("AWT");
awtButton.setOnAction(event -> loadImageFromAwtClipboard(view));
final Button javaFXButton = new Button("JavaFX");
javaFXButton.setOnAction(event -> loadImageFromJavaFXClipboard(view));
root.setCenter(view);
final BorderPane buttonPane = new BorderPane();
buttonPane.setLeft(awtButton);
buttonPane.setCenter(new Label("Copy and image then click a button to paste it."));
buttonPane.setRight(javaFXButton);
root.setBottom(buttonPane);
final ColorPicker colorPicker = new ColorPicker();
colorPicker.setOnAction(event -> {
root.setBackground(
new Background(
new BackgroundFill(
colorPicker.getValue(),
CornerRadii.EMPTY,
Insets.EMPTY)
)
);
});
BorderPane.setAlignment(colorPicker, Pos.CENTER);
root.setTop(colorPicker);
final Scene scene = new Scene(root, 400, 400);
primaryStage.setScene(scene);
primaryStage.show();
listenToClipboard();
}
/**
* This little bit of magic comes courtesy of ÐлекÑÐ°Ð½Ð´Ñ Ð¡Ð°Ð²Ð¾ÑÑÑÑнов: https://stackoverflow.com/a/47550034/5432315
*/
private void listenToClipboard() {
Clipboard clipboard = Clipboard.getSystemClipboard();
new ClipboardAssistance(com.sun.glass.ui.Clipboard.SYSTEM) {
@Override
public void contentChanged() {
System.out.println("System clipboard content changed.");
System.out.println("Clipboard content types: ");
clipboard.getContentTypes().forEach(System.out::println);
System.out.println();
}
};
}
private void loadImageFromJavaFXClipboard(final ImageView view) {
System.out.println("Adding an image from the JavaFX Clipboard...");
final Clipboard clipboard = Clipboard.getSystemClipboard();
if (clipboard.hasImage()) {
final Image image = clipboard.getImage();
view.setImage(image);
} else {
new Alert(Alert.AlertType.INFORMATION, "No image detected on the Clipboard!").show();
}
}
private void loadImageFromAwtClipboard(final ImageView view) {
System.out.println("Adding an image from the AWT Clipboard...");
try {
final Transferable t = Toolkit.getDefaultToolkit().getSystemClipboard().getContents(null);
if (t != null && t.isDataFlavorSupported(DataFlavor.imageFlavor)) {
final java.awt.image.BufferedImage img = (java.awt.image.BufferedImage) t.getTransferData(DataFlavor.imageFlavor);
final Image image = SwingFXUtils.toFXImage(img, null);
view.setImage(image);
} else {
new Alert(Alert.AlertType.INFORMATION, "No image detected on the Clipboard!").show();
}
} catch (final UnsupportedFlavorException | IOException e) {
e.printStackTrace();
}
}
public static void main(final String[] args) {
launch(args);
}
}
---------- END SOURCE ----------
FREQUENCY : always
**The Problem**
JavaFX's default way of getting an image from the Windows clipboard, `Clipboard.getSystemClipboard().getImage();`, appears to be broken.
Something seems to go wrong with the transparency of the image. Set on a black background, the image appears fine, but set on a white background, nothing shows at all.
Here's an animation demonstrating that: https://i.stack.imgur.com/TgszF.gif
The provided source code allows easy comparison between the JavaFX and AWT clipboards.
**What I Know**
This problem with images doesn't occur on the AWT clipboard, just the JavaFX clipboard.
*Problem Applications*
JavaFX seems to have this same transparency problem with various applications that copy an image to the clipboard:
Adobe Reader (from a PDF with images)
Foxit Reader (from a PDF with images)
Here's a pdf with an image, for your convenience: https://drive.google.com/file/d/1waZRrQM6VTN1YzaVSHkxDIzV456Jqi0y/view?usp=sharing
Microsoft Word 365 (from a .docx file with images)
Here's a .docx file with an image, for your convenience: https://drive.google.com/file/d/1s3anuuIXZ4NcJGAbpYakwgqH_YAGPo9x/view?usp=sharing
Windows 7's Paint (.png, .jpg, .gif, .bmp)
Greenshot (which is an enhanced screenshot utility)
Firefox 65.0.2 (copying the Google.com logo)
*Applications Without The Issue*
I've also found a few applications that copy an image to the clipboard and JavaFX can pull it out using the default method no problem:
Paint.net
The PrtScn button
The Windows Snipping Tool
Google Chrome 72.0.3626.121 (copying the Google.com logo)
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. Copy an image from practically any application
[I've been able to replicate this problem with the following applications:
Adobe Reader (from a PDF with images)
Foxit Reader (from a PDF with images)
Microsoft Word 365 (from a .docx file with images)
Windows 7's Paint (.png, .jpg, .gif, .bmp)
Greenshot (which is an enhanced screenshot utility)
Firefox 65.0.2 (copying the Google.com logo)
]
2. Try to create and display an Image from the image copied to the JavaFX Clipboard.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
An image that maintains the same properties as the image that was copied
ACTUAL -
When displayed over something black, the image appears fine, when displayed over something white, no color shows. When displayed on a color in between, various colors do not display correctly, if at all.
Here's an animation of the actual result on numerous backgrounds, using a TV color testing graphic: https://i.stack.imgur.com/TgszF.gif
---------- BEGIN SOURCE ----------
// Instructions: This program allows you to easily compare the JavaFX and the Swing/AWT clipboard.
// First copy an image from some application.
// JavaFX button -> paste the image from the JavaFX clipboard.
// AWT button -> paste the image from the AWT clipboard.
// Use the color changer at the top to see how the image changes based on background that
// the image is displayed on.
package sample;
import com.sun.glass.ui.ClipboardAssistance;
import javafx.application.Application;
import javafx.embed.swing.SwingFXUtils;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.Button;
import javafx.scene.control.ColorPicker;
import javafx.scene.control.Label;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.Clipboard;
import javafx.scene.layout.Background;
import javafx.scene.layout.BackgroundFill;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.CornerRadii;
import javafx.stage.Stage;
import java.awt.*;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.IOException;
/**
* A program to test out the differences between the AWT Java Clipboard and the JavaFX Clipboard.
* <p>
* Based on the code by crusam: https://stackoverflow.com/q/48932575/5432315
*/
public class ClipBoardFxAwtComparison extends Application {
@Override
public void start(final Stage primaryStage) {
final BorderPane root = new BorderPane();
final ImageView view = new ImageView();
final Button awtButton = new Button("AWT");
awtButton.setOnAction(event -> loadImageFromAwtClipboard(view));
final Button javaFXButton = new Button("JavaFX");
javaFXButton.setOnAction(event -> loadImageFromJavaFXClipboard(view));
root.setCenter(view);
final BorderPane buttonPane = new BorderPane();
buttonPane.setLeft(awtButton);
buttonPane.setCenter(new Label("Copy and image then click a button to paste it."));
buttonPane.setRight(javaFXButton);
root.setBottom(buttonPane);
final ColorPicker colorPicker = new ColorPicker();
colorPicker.setOnAction(event -> {
root.setBackground(
new Background(
new BackgroundFill(
colorPicker.getValue(),
CornerRadii.EMPTY,
Insets.EMPTY)
)
);
});
BorderPane.setAlignment(colorPicker, Pos.CENTER);
root.setTop(colorPicker);
final Scene scene = new Scene(root, 400, 400);
primaryStage.setScene(scene);
primaryStage.show();
listenToClipboard();
}
/**
* This little bit of magic comes courtesy of ÐлекÑÐ°Ð½Ð´Ñ Ð¡Ð°Ð²Ð¾ÑÑÑÑнов: https://stackoverflow.com/a/47550034/5432315
*/
private void listenToClipboard() {
Clipboard clipboard = Clipboard.getSystemClipboard();
new ClipboardAssistance(com.sun.glass.ui.Clipboard.SYSTEM) {
@Override
public void contentChanged() {
System.out.println("System clipboard content changed.");
System.out.println("Clipboard content types: ");
clipboard.getContentTypes().forEach(System.out::println);
System.out.println();
}
};
}
private void loadImageFromJavaFXClipboard(final ImageView view) {
System.out.println("Adding an image from the JavaFX Clipboard...");
final Clipboard clipboard = Clipboard.getSystemClipboard();
if (clipboard.hasImage()) {
final Image image = clipboard.getImage();
view.setImage(image);
} else {
new Alert(Alert.AlertType.INFORMATION, "No image detected on the Clipboard!").show();
}
}
private void loadImageFromAwtClipboard(final ImageView view) {
System.out.println("Adding an image from the AWT Clipboard...");
try {
final Transferable t = Toolkit.getDefaultToolkit().getSystemClipboard().getContents(null);
if (t != null && t.isDataFlavorSupported(DataFlavor.imageFlavor)) {
final java.awt.image.BufferedImage img = (java.awt.image.BufferedImage) t.getTransferData(DataFlavor.imageFlavor);
final Image image = SwingFXUtils.toFXImage(img, null);
view.setImage(image);
} else {
new Alert(Alert.AlertType.INFORMATION, "No image detected on the Clipboard!").show();
}
} catch (final UnsupportedFlavorException | IOException e) {
e.printStackTrace();
}
}
public static void main(final String[] args) {
launch(args);
}
}
---------- END SOURCE ----------
FREQUENCY : always