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
Related
I have made a student information page using GUI concept. I want to know that how can i add an image at a specific location using JLabel or any other method? What i want is a background image surrounding the whole Jframe and another image at specific location like at the top right. How can i achieve this?
i also found a code to add image using Jlabel but it doesn't work with my code as my setting the layout to null.
the code i found
String path = "Image1.jpg";
File file = new File(path);
BufferedImage image = ImageIO.read(file);
JLabel label = new JLabel(new ImageIcon(image));
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.getContentPane().add(label);
f.pack();
f.setLocation(200,200);
f.setVisible(true);
Below is my code:
import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.File;
import javax.imageio.ImageIO;
import javax.swing.ButtonGroup;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JRadioButton;
import javax.swing.JTextArea;
import javax.swing.JTextField;
public class LoginPage
{
JFrame jf;
JLabel gender,hobbies,name_label,rollno_label,marks_label,city_label,address_label;
JTextField name_field,rollno_field,marks_field;
JRadioButton male,female;
ButtonGroup bg;
JCheckBox photography,music,sketching,coding;
JComboBox city_combo;
JTextArea adress_textarea;
JButton save, exit;
JMenuBar mbar;
JMenu file,edit,help;
JMenuItem open,save_item,edit_item,close,cut,copy,paste,find,replace,help_content,about,updates;
public LoginPage() //constructor
{
jf = new JFrame("Student Information");
name_label = new JLabel("Student's Name");
name_field = new JTextField();
rollno_label = new JLabel("Student's Roll Number");
rollno_field = new JTextField();
marks_label = new JLabel("Student's Total Marks Achieved");
marks_field = new JTextField();
gender = new JLabel("Gender");
male = new JRadioButton("Male");
female = new JRadioButton("Female");
bg = new ButtonGroup();
hobbies = new JLabel("Hobbies");
photography = new JCheckBox("Photography");
music = new JCheckBox("Music");
coding = new JCheckBox("Coding");
sketching = new JCheckBox("Sketching");
city_label = new JLabel("City");
city_combo = new JComboBox();
address_label = new JLabel("Residential Address");
adress_textarea = new JTextArea();
save = new JButton("Save");
exit = new JButton("Exit");
mbar = new JMenuBar();
file = new JMenu("File");
edit = new JMenu("Edit");
help = new JMenu("Help");
open = new JMenuItem("open");
save_item = new JMenuItem("Save");
edit_item = new JMenuItem("Edit");
close = new JMenuItem("Close");
cut = new JMenuItem("Cut");
copy = new JMenuItem("Copy");
paste = new JMenuItem("Paste");
find = new JMenuItem("Find");
replace = new JMenuItem("Replace");
about = new JMenuItem("About");
updates = new JMenuItem("Check for Updates");
help_content = new JMenuItem("Help Content");
}
void Display()
{
jf.setSize(1000, 700);
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jf.setLayout(null);
jf.getContentPane().setBackground( Color.LIGHT_GRAY );
name_label.setBounds(50, 50, 150, 20);
name_field.setBounds(300, 50, 200, 20);
rollno_label.setBounds(50, 100, 150, 20);
rollno_field.setBounds(300, 100, 200, 20);
marks_label.setBounds(50, 150, 200, 20);
marks_field.setBounds(300, 150, 200, 20);
gender.setBounds(50, 200, 100, 20);
male.setBounds(300, 200, 80, 20);
female.setBounds(400, 200, 80, 20);
hobbies.setBounds(50, 250, 80, 20);
photography.setBounds(300, 250, 100, 20);
music.setBounds(420, 250, 80, 20);
sketching.setBounds(500, 250, 100, 20);
coding.setBounds(600, 250, 80, 20);
city_label.setBounds(50, 300, 100, 20);
city_combo.setBounds(300, 300, 100, 20);
address_label.setBounds(50, 350, 200, 20);
adress_textarea.setBounds(300, 350, 300, 100);
save.setBounds(300, 500, 100, 50);
exit.setBounds(600, 500, 100, 50);
bg.add(male);
bg.add(female);
city_combo.addItem("Select City");
city_combo.addItem("Chandigarh");
city_combo.addItem("Kurali");
city_combo.addItem("Mohali");
city_combo.addItem("Panchkula");
file.add(open);
file.add(save_item);
file.add(edit_item);
file.add(close);
edit.add(cut);
edit.add(copy);
edit.add(paste);
edit.add(find);
edit.add(replace);
help.add(about);
help.add(help_content);
help.add(updates);
mbar.add(file);
mbar.add(edit);
mbar.add(help);
jf.add(name_label);
jf.add(name_field);
jf.add(rollno_label);
jf.add(rollno_field);
jf.add(marks_label);
jf.add(marks_field);
jf.add(gender);
jf.add(male);
jf.add(female);
jf.add(hobbies);
jf.add(music);
jf.add(photography);
jf.add(sketching);
jf.add(coding);
jf.add(city_label);
jf.add(city_combo);
jf.add(address_label);
jf.add(adress_textarea);
jf.add(save);
jf.add(exit);
jf.setJMenuBar(mbar);
jf.setVisible(true);
}
public static void main(String[] args) {
new LoginPage().Display();
}
}
What i want is a background image surrounding the whole Jframe
Suggestions:
Create a class that extends JPanel,
override its paintComponent method
be sure to call the super's paintComponent method in your override
Draw your background image within this method using g.drawImage(...)
Either make this JPanel your JFrame's contentPane or add it to the contentPane BorderLayout.CENTER, and then add your GUI components to this JPanel
Make sure that some of the components are not-opaque, e.g., call setOpaque(false) on your JRadioButtons, and perhaps others, so that the background image shows up.
and another image at specific location like at the top right. How can i achieve this?
Use the same JPanel above, and draw the smaller image using an overload of drawImage(...) that precisely places the image where you want
Notes:
When I create background images for the GUI, I prefer to draw within a JPanel rather than a JLabel since the JLabel is not wired out of the box to act as a contentPane or a decent container.
I strongly advise you not to use null layouts and setBounds as this will lead to gui's that might look good on one platform, but not on another, that have JLabels whose text is not fully seen, that are very difficult to upgrade and maintain. Learn and use the layout managers.
Looks like you're using multiple JFrames. If so, please read: The Use of Multiple JFrames: Good or Bad Practice?
For example, here's one way to display an image as a background image as well as a smaller image in the right upper portion of the GUI, all within a JPanel:
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.*;
#SuppressWarnings("serial")
public class LoginPage3 extends JPanel {
public static final String BG_IMG_PATH = "https://upload.wikimedia.org/wikipedia/"
+ "commons/e/e9/Maesil_%28prunus_mume%29_washed_and_stemmed.jpg";
public static final String RU_IMG_PATH = "https://upload.wikimedia.org/wikipedia/"
+ "commons/thumb/5/5b/Escudo_de_San_Pedro_de_Atacama.svg/200px-Escudo_de_San_Pedro_de_Atacama.svg.png";
private BufferedImage backgroundImg;
private BufferedImage rightUpperImg;
public LoginPage3(BufferedImage bgImg, BufferedImage ruImg) {
this.backgroundImg = bgImg;
this.rightUpperImg = ruImg;
}
#Override
public Dimension getPreferredSize() {
if (backgroundImg == null || isPreferredSizeSet()) {
return super.getPreferredSize();
} else {
int w = backgroundImg.getWidth();
int h = backgroundImg.getHeight();
return new Dimension(w, h);
}
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (backgroundImg != null) {
g.drawImage(backgroundImg, 0, 0, this);
}
if (rightUpperImg != null) {
int x = getWidth() - rightUpperImg.getWidth();
g.drawImage(rightUpperImg, x, 0, this);
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
private static void createAndShowGui() {
BufferedImage bg = null;
BufferedImage ru = null;
try {
bg = ImageIO.read(new URL(BG_IMG_PATH));
ru = ImageIO.read(new URL(RU_IMG_PATH));
} catch (IOException e) {
e.printStackTrace();
System.exit(-1);
}
LoginPage3 mainPanel = new LoginPage3(bg, ru);
JFrame frame = new JFrame("LoginPage3");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
For background image:
Load it as an icon, and create a JLabel with it. (See your first snippet)
Set the JLabel as the JFrame's content pane.
All you have to take care of, that Icon does not stretch, so you have to have an image that is exactly the same size as your JFrame (or larger).
As for the image at a given position, the JLabel creating and Icon loading process is the same, but after adding it to the JFrame you have to set position and size, just like for your other components, EG call setBounds()...
When i load image ,it do not load at upper left (if the image is large to be fit on window size).This is because i diminish its size as shown in code. Although i am giving its coordinate value 0,0 it is not drawing at that position.
import javax.swing.*;
import javax.imageio.ImageIO;
import java.io.*;
import java.awt.*;
import java.awt.image.BufferedImage;
public class photo extends JFrame
{
Dimension screenwidth=getToolkit().getScreenSize();
int mx=(int)screenwidth.getWidth();
int my=(int)screenwidth.getHeight();
BufferedImage picture1;
JLabel label3;
int neww;
int newh;
public photo() {
JFrame f = new JFrame("Image Editor v1.0");
f.setLayout(null);
try{
File file=new File("e:\\8.jpg");
picture1=ImageIO.read(file);
}catch(Exception e)
{
}
JPanel panel2 = new JPanel();
panel2.setLayout(null);
panel2.setBounds(101,20,mx-100,my-20);
f.add(panel2);
label3 = new JLabel("");
label3.setBounds(110,30,mx-110,my-30);
panel2.add(label3);
f.setExtendedState(Frame.MAXIMIZED_BOTH);
f.setVisible(true);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
BufferedImage bi = null;
if(picture1.getWidth()>mx-110 ||picture1.getHeight()>my-30 )
{
neww= (int) Math.round(picture1.getWidth() * 0.25);
newh = (int) Math.round(picture1.getHeight() *0.25);
}
else
{
neww=picture1.getWidth();
newh=picture1.getHeight();
}
bi = new BufferedImage(neww,newh,BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = (Graphics2D) bi.createGraphics();
g2d.addRenderingHints(new RenderingHints(RenderingHints.KEY_RENDERING,RenderingHints.VALUE_RENDER_QUALITY));
g2d.drawImage(picture1,0,0,neww,newh,0,0,picture1.getWidth(),picture1.getHeight(), null);
label3.setIcon(new ImageIcon(bi));
}
public static void main(String[] args)
{
new photo();
}
}
You could add g2d.translate(0, 0); between g2d.addRenderingHints and g2d.drawImage and try it.
EDIT
So if you want the image to be at 101 px and 20 px, you should label3.setBounds(0,0,neww,newh); after label3.setIcon(new ImageIcon(bi)); instead of the current. I think this shall work as I have just tested.
I would like, for a java project, to change the color of a hair modelisation (to change hair color) with shadows and reflects...
In fact, I wondered if there's a class which can change the color of a picture with a RGB code. If this can help you, here's the picture I need to colorize :
I assume that the question targeted NOT at blindly replacing certain pixels with a certain (fixed) color, but at really "dyeing" the image. Once I wrote a sample class showing how this could be done:
import java.awt.*;
import java.awt.image.*;
import java.io.*;
import javax.swing.*;
import javax.imageio.*;
class DyeImage
{
public static void main(String args[])
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
try
{
new DyeImage();
}
catch (Exception e)
{
e.printStackTrace();
}
}
});
}
public DyeImage() throws Exception
{
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
BufferedImage image = ImageIO.read(new File("DRVpH.png"));
JPanel panel = new JPanel(new GridLayout(1,0));
panel.add(new JLabel(new ImageIcon(image)));
panel.add(new JLabel(new ImageIcon(dye(image, new Color(255,0,0,128)))));
panel.add(new JLabel(new ImageIcon(dye(image, new Color(255,0,0,32)))));
panel.add(new JLabel(new ImageIcon(dye(image, new Color(0,128,0,32)))));
panel.add(new JLabel(new ImageIcon(dye(image, new Color(0,0,255,32)))));
f.getContentPane().add(panel);
f.pack();
f.setVisible(true);
}
private static BufferedImage dye(BufferedImage image, Color color)
{
int w = image.getWidth();
int h = image.getHeight();
BufferedImage dyed = new BufferedImage(w,h,BufferedImage.TYPE_INT_ARGB);
Graphics2D g = dyed.createGraphics();
g.drawImage(image, 0,0, null);
g.setComposite(AlphaComposite.SrcAtop);
g.setColor(color);
g.fillRect(0,0,w,h);
g.dispose();
return dyed;
}
}
The result with the given image and different dyeing colors will look like this:
I'm trying to write a program that will allow me to put text over an image, and save the edited image. Right now I'm getting an error that says:
Exception in thread "main" java.lang.IllegalArgumentException: adding a window to a container
When I run the code it shows the text box, and a white background without my image. Any help with this would be appreciated. Right now i'm just focused on getting the text field over the image. Thank you in advance!
Here's the code:
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import java.io.*;
import javax.imageio.*;
import javax.swing.*;
import java.util.TreeSet;
public class Try1 extends JFrame {
public Try1() {
initializeUI();
}
BufferedImage img;
public void paint(Graphics g) {
g.drawImage(img, 0, 0, null);
}
public void LoadImage() {
try {
img = ImageIO.read(new File("savedimage.jpg"));
}
catch (IOException e){}
}
private void initializeUI() {
JPanel panel = new JPanel(null);
setSize(400, 400);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JTextField textField = new JTextField(20);
textField.setBounds(50, 50, 100, 20);
panel.add(textField);
setContentPane(panel);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new Try1().setVisible(true);
}
});
JFrame f = new JFrame("Load Image Sample");
f.addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
f.add(new Try1());
f.pack();
f.setVisible(true);
}
}
A better approach in general can be seen in LabelRenderTest.
You only need to use HTML formatting in the label if multi-line text is required. Use plain text for a single line message.
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);
}
});
}
}
Following JFrame is useless. Because Try1 is itself a JFrame.
JFrame f = new JFrame("Load Image Sample");
basically just use Try1 instead of other Jframe.
f = new Try1();
f.pack();
f.setVisible(true);
But more importantly, you should not override paint, overide paintComponent instead. See Difference between paint() and paintcomponent()?.
This is your problem
JFrame f = new JFrame("Load Image Sample");
f.addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
This is not a window. It is a JFrame, so it is unwise to put a WindowAdapter on it
Your class is extending a JFrame, so take out the JFrame, and just do your
new Try1();
f.pack();
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