|
1 | 1 | /******************************************************************************* |
2 | | - * Copyright (c) 2015-2017 Oak Ridge National Laboratory. |
| 2 | + * Copyright (c) 2015-2025 Oak Ridge National Laboratory. |
3 | 3 | * All rights reserved. This program and the accompanying materials |
4 | 4 | * are made available under the terms of the Eclipse Public License v1.0 |
5 | 5 | * which accompanies this distribution, and is available at |
6 | 6 | * http://www.eclipse.org/legal/epl-v10.html |
7 | 7 | *******************************************************************************/ |
8 | 8 | package org.phoebus.ui.javafx; |
9 | 9 |
|
10 | | -import java.awt.image.BufferedImage; |
11 | | -import java.io.File; |
12 | | - |
13 | | -import javax.imageio.ImageIO; |
14 | | - |
15 | 10 | import javafx.embed.swing.SwingFXUtils; |
16 | 11 | import javafx.scene.Node; |
17 | 12 | import javafx.scene.Scene; |
18 | 13 | import javafx.scene.image.Image; |
19 | 14 | import javafx.scene.image.WritableImage; |
20 | 15 | import javafx.scene.input.Clipboard; |
21 | 16 |
|
22 | | -/** Create screenshot of a JavaFX scene |
23 | | - * @author Kay Kasemir |
| 17 | +import javax.imageio.ImageIO; |
| 18 | +import java.awt.*; |
| 19 | +import java.awt.datatransfer.DataFlavor; |
| 20 | +import java.awt.datatransfer.Transferable; |
| 21 | +import java.awt.datatransfer.UnsupportedFlavorException; |
| 22 | +import java.awt.image.BufferedImage; |
| 23 | +import java.io.File; |
| 24 | + |
| 25 | +/** |
| 26 | + * Create screenshot of a JavaFX scene |
| 27 | + * |
| 28 | + * @author Kay Kasemir |
24 | 29 | */ |
25 | 30 | @SuppressWarnings("nls") |
26 | | -public class Screenshot |
27 | | -{ |
| 31 | +public class Screenshot { |
28 | 32 | private final BufferedImage image; |
29 | 33 |
|
30 | | - /** Initialize screenshot |
| 34 | + /** |
| 35 | + * Initialize screenshot |
| 36 | + * |
| 37 | + * <p>Must be called on UI thread |
31 | 38 | * |
32 | | - * <p>Must be called on UI thread |
33 | | - * @param scene Scene to capture |
| 39 | + * @param scene Scene to capture |
34 | 40 | */ |
35 | | - public Screenshot(final Scene scene) |
36 | | - { |
| 41 | + public Screenshot(final Scene scene) { |
37 | 42 | image = bufferFromNode(scene.getRoot()); |
38 | 43 | } |
39 | 44 |
|
40 | | - public Screenshot(final Node node) |
41 | | - { |
| 45 | + public Screenshot(final Node node) { |
42 | 46 | image = bufferFromNode(node); |
43 | 47 | } |
44 | 48 |
|
45 | | - public Screenshot(final Image image) |
46 | | - { |
| 49 | + public Screenshot(final Image image) { |
47 | 50 | this.image = bufferFromImage(image); |
48 | 51 | } |
49 | 52 |
|
50 | | - /** Get a JavaFX Node Snapshot as a JavaFX Image |
| 53 | + /** |
| 54 | + * Get a JavaFX Node Snapshot as a JavaFX Image |
| 55 | + * |
51 | 56 | * @param node |
52 | 57 | * @return Image |
53 | 58 | */ |
54 | | - public static WritableImage imageFromNode(Node node) |
55 | | - { |
| 59 | + public static WritableImage imageFromNode(Node node) { |
56 | 60 | return node.snapshot(null, null); |
57 | 61 | } |
58 | 62 |
|
59 | | - /** Get a AWT BufferedImage from JavaFX Image |
60 | | - * @param jfx {@link Image} |
61 | | - * @return BufferedImage |
| 63 | + /** |
| 64 | + * Get a AWT BufferedImage from JavaFX Image |
| 65 | + * |
| 66 | + * @param jfx {@link Image} |
| 67 | + * @return BufferedImage |
62 | 68 | */ |
63 | | - public static BufferedImage bufferFromImage(final Image jfx) |
64 | | - { |
65 | | - final BufferedImage img = new BufferedImage((int)jfx.getWidth(), |
66 | | - (int)jfx.getHeight(), |
| 69 | + public static BufferedImage bufferFromImage(final Image jfx) { |
| 70 | + final BufferedImage img = new BufferedImage((int) jfx.getWidth(), |
| 71 | + (int) jfx.getHeight(), |
67 | 72 | BufferedImage.TYPE_INT_ARGB); |
68 | 73 | SwingFXUtils.fromFXImage(jfx, img); |
69 | 74 |
|
70 | 75 | return img; |
71 | 76 | } |
72 | 77 |
|
73 | | - /** Get a JavaFX Node Snapshot as an AWT BufferedImage |
| 78 | + /** |
| 79 | + * Get a JavaFX Node Snapshot as an AWT BufferedImage |
| 80 | + * |
74 | 81 | * @param node |
75 | 82 | * @return BufferedImage |
76 | 83 | */ |
77 | | - public static BufferedImage bufferFromNode(Node node) |
78 | | - { |
| 84 | + public static BufferedImage bufferFromNode(Node node) { |
79 | 85 | return bufferFromImage(imageFromNode(node)); |
80 | 86 | } |
81 | 87 |
|
@@ -104,47 +110,84 @@ public static Image captureScreen() |
104 | 110 | /** |
105 | 111 | * Get an image from the clip board. |
106 | 112 | * <p> Returns null if no image is on the clip board. |
| 113 | + * |
107 | 114 | * @return Image |
108 | 115 | */ |
109 | | - public static Image getImageFromClipboard() |
110 | | - { |
| 116 | + public static Image getImageFromClipboard() { |
111 | 117 | Clipboard clipboard = Clipboard.getSystemClipboard(); |
112 | 118 | return clipboard.getImage(); |
113 | 119 | } |
114 | 120 |
|
115 | | - /** Write to file |
116 | | - * @param file Output file |
117 | | - * @throws Exception on error |
| 121 | + /** |
| 122 | + * Write to file |
| 123 | + * |
| 124 | + * @param file Output file |
| 125 | + * @throws Exception on error |
118 | 126 | */ |
119 | | - public void writeToFile(final File file) throws Exception |
120 | | - { |
121 | | - try |
122 | | - { |
| 127 | + public void writeToFile(final File file) throws Exception { |
| 128 | + try { |
123 | 129 | ImageIO.write(image, "png", file); |
124 | | - } |
125 | | - catch (Exception ex) |
126 | | - { |
| 130 | + } catch (Exception ex) { |
127 | 131 | throw new Exception("Cannot create screenshot " + file.getAbsolutePath(), ex); |
128 | 132 | } |
129 | 133 | } |
130 | 134 |
|
131 | | - /** Write to temp. file |
132 | | - * @param file_prefix File prefix |
133 | | - * @return File that was created |
134 | | - * @throws Exception on error |
| 135 | + /** |
| 136 | + * Write to temp. file |
| 137 | + * |
| 138 | + * @param file_prefix File prefix |
| 139 | + * @return File that was created |
| 140 | + * @throws Exception on error |
135 | 141 | */ |
136 | | - public File writeToTempfile(final String file_prefix) throws Exception |
137 | | - { |
138 | | - try |
139 | | - { |
| 142 | + public File writeToTempfile(final String file_prefix) throws Exception { |
| 143 | + try { |
140 | 144 | final File file = File.createTempFile(file_prefix, ".png"); |
141 | 145 | file.deleteOnExit(); |
142 | 146 | writeToFile(file); |
143 | 147 | return file; |
144 | | - } |
145 | | - catch (Exception ex) |
146 | | - { |
| 148 | + } catch (Exception ex) { |
147 | 149 | throw new Exception("Cannot create tmp. file:\n" + ex.getMessage()); |
148 | 150 | } |
149 | 151 | } |
| 152 | + |
| 153 | + /** |
| 154 | + * Puts the {@link Node} as image data onto the clipboard. |
| 155 | + * |
| 156 | + * @param node Node from which to take a screenshot. |
| 157 | + */ |
| 158 | + public static void copyToClipboard(Node node) { |
| 159 | + BufferedImage bufferedImage = bufferFromNode(node); |
| 160 | + Toolkit.getDefaultToolkit().getSystemClipboard().setContents(new TransferableImage(bufferedImage), null); |
| 161 | + } |
| 162 | + |
| 163 | + /** |
| 164 | + * Minimal implementation to support putting image data on the clipboard |
| 165 | + */ |
| 166 | + private static class TransferableImage implements Transferable { |
| 167 | + |
| 168 | + private final java.awt.Image image; |
| 169 | + |
| 170 | + public TransferableImage(java.awt.Image image) { |
| 171 | + this.image = image; |
| 172 | + } |
| 173 | + |
| 174 | + @Override |
| 175 | + public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException { |
| 176 | + if (flavor.equals(DataFlavor.imageFlavor) && image != null) { |
| 177 | + return image; |
| 178 | + } else { |
| 179 | + throw new UnsupportedFlavorException(flavor); |
| 180 | + } |
| 181 | + } |
| 182 | + |
| 183 | + @Override |
| 184 | + public DataFlavor[] getTransferDataFlavors() { |
| 185 | + return new DataFlavor[]{DataFlavor.imageFlavor}; |
| 186 | + } |
| 187 | + |
| 188 | + @Override |
| 189 | + public boolean isDataFlavorSupported(DataFlavor flavor) { |
| 190 | + return flavor.equals(DataFlavor.imageFlavor); |
| 191 | + } |
| 192 | + } |
150 | 193 | } |
0 commit comments