Swing:获取JFrame的图像 [英] Swing: Obtain Image of JFrame

查看:117
本文介绍了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;

/ **
创建组件的屏幕截图。
@author Andrew Thompson
* /
class ComponentImageCapture {

static final String HELP =
键入Ctrl-0以获取当前的屏幕截图GUI.\\\
+
屏幕截图将以'screenshot.png'的形式保存到当前的+
目录中。;

public static BufferedImage getScreenShot(
Component component){

BufferedImage image = new BufferedImage(
component.getWidth(),
component .getHeight(),
BufferedImage.TYPE_INT_RGB
);
//使用
//图像的Graphics对象调用Component的paint方法。
component.paint(image.getGraphics()); //交替使用.printAll(..)
返回图片;
}

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(
新的ActionListener(){
公共无效的actionPerformed(ActionEvent的AE){
的BufferedImage IMG = getScreenShot(
f.getContentPane());
JOptionPane.showMessageDialog(
空,
新的JLabel(
新的ImageIcon(
img.getScaledInstance(
img.getWidth(空)/ 2,
img.getHeight(null)/ 2,
Image.SCALE_SMOOTH)
)));
try {
//将图像写为PNG
ImageIO .write(
img,
png,
new File(screenshot.png));
} catch(例外e){
e.printStackTrace ();
}
}
});
JMenu menu = new JMenu(Other);
menu.add(screenshot);
JMenuBar mb = new JMenuBar();
mb.add(菜单);
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展示了如何在屏幕图像中绘制未实现的组件另一个可能相关的线程是在没有第一次显示的情况下渲染JLabel ,特别是Darryl Burke的一线修复。





LabelRenderTest.java



以下是第二个链接上显示的代码的更新变体。

  import java.awt。*; 
import java.awt.image.BufferedImage;
import javax.swing。*;

公共类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我?< / h1>
+这是一个将换行的长字符串。
+我们想要的效果是一个多行标签。;

的JFrame F =新的JFrame( 标记渲染测试);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

BufferedImage的图像=新的BufferedImage(
400,
300,
BufferedImage.TYPE_INT_RGB);
的Graphics2D imageGraphics = image.createGraphics();
的GradientPaint GP =新的GradientPaint(
20F,
20分配f,
Color.red,
380f,
280f,
Color.orange);
imageGraphics.setPaint(gp);
imageGraphics.fillRect(0,0,400,300);

JLabel textLabel = new JLabel(title);
textLabel.setSize(textLabel.getPreferredSize());

维度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);
图形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);
}
});
}
}



截屏




How do I obtain a java.awt.Image of a JFrame?

I want to obtain a screen shot of a JFrame (for later use within my application). This is presently accomplished using the robot to take a screen shot specifying the coordinates and dimensions of the JFrame involved.

However, I believe that there is a better way: Swing components, by default, render themselves as images into a double buffer prior to painting themselves onto the screen.

Is there a way to obtain these images from the component?

解决方案

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);
  }
} 

Screen shot

See also

The code shown above presumes the component has been realized on-screen, prior to rendering.

Rob Camick shows how to paint an unrealized component in the Screen Image class.

Another thread that might be of relevance, is Render JLabel without 1st displaying, particularly the 'one line fix' by Darryl Burke.

LabelRenderTest.java

Here is an updated variant of the code shown on the second link.

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 U C 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);
            }
        });
    }
}

Screen shot

这篇关于Swing:获取JFrame的图像的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆