Swing:获取JFrame的图像
我如何获得JFrame的java.awt.Image
?
我想获得一个JFrame
的屏幕截图(在我的应用程序中稍后使用)。 目前通过使用机器人来完成指定所涉及的JFrame
的坐标和尺寸的屏幕截图。
不过,我相信还有一个更好的方法:默认情况下,Swing组件在将自己绘制到屏幕上之前将其自身渲染为双缓冲区。
有没有办法从组件获取这些图像?
ComponentImageCapture.java
import java.awt.BorderLayout; import java.awt.Component; import java.awt.Image; import java.awt.Graphics; import java.awt.image.BufferedImage; import java.awt.event.ActionListener; import java.awt.event.ActionEvent; import java.awt.event.KeyEvent; import java.awt.event.InputEvent; import javax.swing.*; import javax.swing.border.TitledBorder; import javax.imageio.ImageIO; import java.io.File; /** Create a screenshot of a component. @author Andrew Thompson */ class ComponentImageCapture { static final String HELP = "Type Ctrl-0 to get a screenshot of the current GUI.\n" + "The screenshot will be saved to the current " + "directory as 'screenshot.png'."; public static BufferedImage getScreenShot( Component component) { BufferedImage image = new BufferedImage( component.getWidth(), component.getHeight(), BufferedImage.TYPE_INT_RGB ); // call the Component's paint method, using // the Graphics object of the image. component.paint( image.getGraphics() ); // alternately use .printAll(..) return image; } public static void main(String[] args) { Runnable r = new Runnable() { public void run() { final JFrame f = new JFrame("Test Screenshot"); JMenuItem screenshot = new JMenuItem("Screenshot"); screenshot.setAccelerator( KeyStroke.getKeyStroke( KeyEvent.VK_0, InputEvent.CTRL_DOWN_MASK )); screenshot.addActionListener( new ActionListener(){ public void actionPerformed(ActionEvent ae) { BufferedImage img = getScreenShot( f.getContentPane() ); JOptionPane.showMessageDialog( null, new JLabel( new ImageIcon( img.getScaledInstance( img.getWidth(null)/2, img.getHeight(null)/2, Image.SCALE_SMOOTH ) ))); try { // write the image as a PNG ImageIO.write( img, "png", new File("screenshot.png")); } catch(Exception e) { e.printStackTrace(); } } } ); JMenu menu = new JMenu("Other"); menu.add(screenshot); JMenuBar mb = new JMenuBar(); mb.add(menu); f.setJMenuBar(mb); JPanel p = new JPanel( new BorderLayout(5,5) ); p.setBorder( new TitledBorder("Main GUI") ); p.add( new JScrollPane(new JTree()), BorderLayout.WEST ); p.add( new JScrollPane( new JTextArea(HELP,10,30) ), BorderLayout.CENTER ); f.setContentPane( p ); f.pack(); f.setLocationRelativeTo(null); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); f.setVisible(true); } }; SwingUtilities.invokeLater(r); } }
屏幕截图
也可以看看
上面显示的代码假定组件在渲染之前已经在屏幕上实现了。
Rob Camick演示了如何在Screen Image类中绘制未实现的组件。
另一个可能相关的线程是Render JLabel,没有第一个显示 ,特别是Darryl Burke的“单行修正”。
LabelRenderTest.java
这里是第二个链接上显示的代码的更新变体。
import java.awt.*; import java.awt.image.BufferedImage; import javax.swing.*; public class LabelRenderTest { public static void main(String[] args) { SwingUtilities.invokeLater( new Runnable() { public void run() { String title = "<html><body style='width: 200px; padding: 5px;'>" + "<h1>Do UC Me?</h1>" + "Here is a long string that will wrap. " + "The effect we want is a multi-line label."; JFrame f = new JFrame("Label Render Test"); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); BufferedImage image = new BufferedImage( 400, 300, BufferedImage.TYPE_INT_RGB); Graphics2D imageGraphics = image.createGraphics(); GradientPaint gp = new GradientPaint( 20f, 20f, Color.red, 380f, 280f, Color.orange); imageGraphics.setPaint(gp); imageGraphics.fillRect(0, 0, 400, 300); JLabel textLabel = new JLabel(title); textLabel.setSize(textLabel.getPreferredSize()); Dimension d = textLabel.getPreferredSize(); BufferedImage bi = new BufferedImage( d.width, d.height, BufferedImage.TYPE_INT_ARGB); Graphics g = bi.createGraphics(); g.setColor(new Color(255, 255, 255, 128)); g.fillRoundRect( 0, 0, bi.getWidth(f), bi.getHeight(f), 15, 10); g.setColor(Color.black); textLabel.paint(g); Graphics g2 = image.getGraphics(); g2.drawImage(bi, 20, 20, f); ImageIcon ii = new ImageIcon(image); JLabel imageLabel = new JLabel(ii); f.getContentPane().add(imageLabel); f.pack(); f.setLocationByPlatform(true); f.setVisible(true); } }); } }