Jframe image + textfield - java

Hi i am trying to make a simple frame displaying an image a textfield and a button, but for some reason the textfield is invisible, since i am quite nooby at java and even more at these graphical things can you help :)
THE CODE
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package solverapplet;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.File;
import javax.swing.JTextField;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import sun.misc.BASE64Decoder;
public class AwtImage extends Frame{
Image img;
String base="R0lGODlhDwAPAKECAAAAzMzM/////wAAACwAAAAADwAPAAACIISPeQHsrZ5ModrLlN48CXF8m2iQ3YmmKqVlRtW4MLwWACH+H09wdGltaXplZCBieSBVbGVhZCBTbWFydFNhdmVyIQAAOw==";
/*public static void main(String[] args){
AwtImage ai = new AwtImage();
}*/
public void setbase(String a){
this.base=a;
}
public void refreshimage(){
try {
BASE64Decoder decoder = new BASE64Decoder();
byte[] imgBytes = decoder.decodeBuffer(this.base);
BufferedImage bufImg = ImageIO.read(new ByteArrayInputStream(imgBytes));
//File imgOutFile = new File("newLabel.png");
//ImageIO.write(bufImg, "png", imgOutFile);
img = bufImg;
} catch (IOException ex) {
Logger.getLogger(AwtImage.class.getName()).log(Level.SEVERE, null, ex);
}
}
public AwtImage(){
super("Solve");
try {
BASE64Decoder decoder = new BASE64Decoder();
byte[] imgBytes = decoder.decodeBuffer(this.base);
BufferedImage bufImg = ImageIO.read(new ByteArrayInputStream(imgBytes));
MediaTracker mt = new MediaTracker(this);
img=bufImg;
mt.addImage(img,0);
JTextField textfield= new JTextField("Text field 2", 8);
add(textfield,"South");
setSize(400,400);
//pack();
setVisible(true);
addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent we){
dispose();
}
});
} catch (IOException ex) {
Logger.getLogger(AwtImage.class.getName()).log(Level.SEVERE, null, ex);
}
}
public void update(Graphics g){
paint(g);
}
public void paint(Graphics g){
if(img != null)
g.drawImage(img, 100, 100, this);
else
g.clearRect(0, 0, getSize().width, getSize().height);
}
}
It gets instantiated by an other class.

The problem is, you've overridden the paint method without making a call to it's super, meaning that it never gets a chance to paint.
public void paint(Graphics g){
if(img != null)
g.drawImage(img, 100, 100, this);
else
g.clearRect(0, 0, getSize().width, getSize().height);
}
When using java.awt.Frame you will find it difficult to achieve what you. java.swingx.JFrame allows you to override the paintComponent method, which allows you to paint the background of the component, but the java.awt.Frame does not.
You should also avoid mixing light and heavy weight components (I know, it's apparently fixed), but if you can, just avoid it.

Related

Brighten Image(JLabel) on a JFrame on hover

I have a JLabel image on a JFrame that I want too brighten upon hovering, have tried a few things however nothing seems to be working, here's my current code:
public class DivinationLogo extends JLabel {
private BufferedImage logo;
public DivinationLogo() {
super();
try {
logo = ImageIO.read(getClass().getResourceAsStream("/assets/images/logo.png"));
} catch (IOException e) {
e.printStackTrace();
}
// setIcon(new ImageIcon(logo));
setIconTextGap(0);
setBorder(null);
setText(null);
addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
Functions.openWebPage(Config.website);
}
#Override
public void mouseEntered(MouseEvent e) {
Functions.brightnessControl(logo, .3F);
}
#Override
public void mouseExited(MouseEvent e) {
Functions.brightnessControl(logo, 1.0F);
}
});
setBounds(-5, 1, 247, 106);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(logo, -5, 1, null);
}
}
Functions.brightnessControl:
public static Image brightnessControl(Image image, float brightness) {
BufferedImage bi = new BufferedImage(image.getWidth(null), image.getHeight(null), BufferedImage.TYPE_INT_ARGB);
Graphics bg = bi.getGraphics();
if (bi.getColorModel().hasAlpha()) {
System.out.println("Image has got an alpha channel");
}
bg.drawImage(image, 0, 0, null);
bg.dispose();
RescaleOp rescaleOp = new RescaleOp(brightness, 0, null);
rescaleOp.filter(bi, bi);
image = bi;
return bi;
}
Currently, it does nothing which confuses me. If anyone knows how this is achieved, please feel free too let me know :)
Ok, so the basic idea is, when the mouse enters the component, you want to generate a "bright" version of the component (I know, obvious, but bear with me)
The problem is, you have a Graphics context and you need a image :/
The following is not overly optimised, but without spending a lot of time adding in PropertyChange support, this will give you the basic idea.
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagLayout;
import java.awt.Image;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.awt.image.RescaleOp;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
JFrame frame = new JFrame();
frame.setLayout(new GridBagLayout());
JLabel label = new BrightLabel();
label.setIcon((new ImageIcon(ImageIO.read(Main.class.getResource("background.png")))));
frame.add(label);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
} catch (IOException ex) {
ex.printStackTrace();
}
}
});
}
public class BrightLabel extends JLabel {
private MouseAdapter mouseHandler;
private boolean isHover = false;
#Override
public void addNotify() {
super.addNotify();
mouseHandler = new MouseAdapter() {
#Override
public void mouseEntered(MouseEvent e) {
isHover = true;
repaint();
}
#Override
public void mouseExited(MouseEvent e) {
isHover = false;
repaint();
}
};
System.out.println("...");
addMouseListener(mouseHandler);
}
#Override
public void removeNotify() {
super.removeNotify();
if (mouseHandler != null) {
removeMouseListener(mouseHandler);
}
mouseHandler = null;
}
#Override
protected void paintComponent(Graphics g) {
if (!isHover) {
super.paintComponent(g);
return;
}
BufferedImage img = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = img.createGraphics();
super.paintComponent(g2d);
g2d.dispose();
Image bright = brightnessControl(img, 1.3f);
g.drawImage(bright, 0, 0, this);
}
public Image brightnessControl(Image image, float brightness) {
BufferedImage bi = new BufferedImage(image.getWidth(null), image.getHeight(null), BufferedImage.TYPE_INT_ARGB);
Graphics bg = bi.getGraphics();
if (bi.getColorModel().hasAlpha()) {
System.out.println("Image has got an alpha channel");
}
bg.drawImage(image, 0, 0, null);
bg.dispose();
RescaleOp rescaleOp = new RescaleOp(brightness, 0, null);
rescaleOp.filter(bi, bi);
image = bi;
return bi;
}
}
}
Essentially, when the mouse enters or exists the component, we set the isHover property. We then call repaint to trigger a new paint pass.
When the component is painted, if isHover is true, we take over the painting process slightly, generating our own buffer and painting the component to it. This gives us our base image. From there we brighten the image and paint it to the Graphics context
Arguments in java are passed by value so your the function you have to brighten the image doesn't have an effect on the image you passed to it.
You're missing the repaint() call after changing the image.
You definitely don't want to prepare the hover image every time you hover over the image. Pre-calculate the hover in the constructor and assign it to a separate image.
Create a member variable for if hover is true and use that in the paint method to figure out which image to paint.

How do I display a BufferedImage in a JComponent?

I have been trying this for hours now. I have a class that extends JComponent, and in its paintComponent I am trying to draw an image, but I am not being able to. Here is my code:
public class Main extends JComponent{
public static void main(String[] args) {
Main main = new Main();
JFrame frame = new JFrame(Info.getGameTitle());
frame.add(main);
frame.setSize(Info.getWidth(), Info.getHeight());
frame.setResizable(false);
frame.addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent e){
System.out.println("Window closed");
System.exit(0);
}
});
frame.setAlwaysOnTop(true);
frame.setFocusable(true);
frame.setAutoRequestFocus(true);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
Graphics g = main.getGraphics();
main.paint(g);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
BufferedImage image = null;
try {
image = ImageIO.read(new FileInputStream("images/01.jpg"));
}catch(FileNotFoundException e) {
System.out.println("Could not find file!");
e.printStackTrace();
}catch(IOException e) {
System.out.println("Could not read file!");
e.printStackTrace();
}
g.drawImage(image, 0, 0, this);
}
}
It is not throwing any exceptions, so the image appears to be loaded. However, nothing appears on the screen. If I try to draw shapes or text, that works fine.
What am I doing wrong?
EDIT: Now I have supplied a working example.
Be aware that your JComponent may be painted hundreds of times per second,
for example when it is partially obscured by another moving window.
So, performance of the paint methods is important, or else you get a "laggy" GUI.
Therefore I suggest to separate the time-consuming part (i.e. reading the image file) from the JComponent.
public class ImageComponent extends JComponent {
private BufferedImage image;
public void setImage(final BufferedImage image) {
this.image = image;
repaint();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (image != null)
g.drawImage(image, 0, 0, this);
}
}
Somewhere else in your code you read the image file and set it into the component:
BufferedImage image = null;
try {
image = ImageIO.read(new File(fullpathname+"/01.jpg"));
}catch(Exception e) {
System.out.println("Could not read file!");
e.printStackTrace();
}
ImageComponent component = new ImageComponent();
component.setImage(image);
Graphics g = main.getGraphics();
main.paint(g);
No, no, no, NO, NO! A infinite times NO! This is not how painting works!
Take a look at Performing Custom Painting and Painting in AWT and Swing for a better understanding of how painting works in Swing.
getGraphics can return null and will only return the last used context to paint the component, anything painted to it will be erased on the next paint cycle.
There is never a good reason to call paint manually, just don't do it.
You should be do something more along the lines of
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.FileInputStream;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private BufferedImage img = null;
public TestPane() {
try {
img = ImageIO.read(new FileInputStream("..."));
} catch (IOException ex) {
ex.printStackTrace();
}
}
#Override
public Dimension getPreferredSize() {
return img == null ? new Dimension(200, 200) : new Dimension(img.getWidth(), img.getHeight());
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
if (img != null) {
g2d.drawImage(img, 0, 0, this);
}
g2d.dispose();
}
}
}
If your image is still not showing up, I suspect that the image is misplaced.
new FileInputStream("images/01.jpg")
suggests that the image resides within the current directory from where the program is been executed, this is not always the same as where the program resides.
You can use System.getProperty("user.dir") to determine the current "working" directory and compare it to where you think the program resides. You can also use File#exists to test if the file exists or not, although, I would have expected the code to throw an IOException if that were the case.
A better long term solution would be to embedded the image within application (typically including it in the Jar), this removes the above issues.
In that case you'd need to use...
ImageIO.read(getClass().getResource("/images/01.jpg"));
to load the image
Try this:
Image image = ImageIO.read(new File(file));
g.drawImage(image, 0, 0, this);
Try this
BufferedImage image = null;
try {
image = ImageIO.read(new File(fullpathname+"/01.jpg"));
}catch(Exception e) {
System.out.println("Could not read file!");
e.printStackTrace();
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(image, 0, 0, this);
}
read throws more exceptions
IllegalArgumentException - if input is null.
IOException - if an error occurs during reading.
so catching the more general one (Exception) will cover it

Drawing an image on top of an image in a JComponent erases part of the bottom image

I am making a 2d game and I need to draw an image on top of another. After I draw the first image(the larger one, jpg), the second image(the smaller one,png) erases from where the second image is to the lower right hand corner. Like this:
I have looked into this a bit, and it was suggested that I use buffered images, so I did that with both images and the problem remains. Here is one post I looked at: How to draw an image over another image?. I have also seen some people suggesting graphics2d, though I did not really understand the reason to use them or how to use them. I am new to java graphics and images, so it is probably a silly mistake.
Here is my code. Thank you.
import java.awt.*;
import java.awt.event.*;
import java.net.*;
import javax.swing.*;
import java.util.ArrayList;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import java.io.IOException;
public class DisplayExample extends JComponent
{
private BufferedImage backgroundImage;
private String backgroundName;
private BufferedImage image; //image to draw
private int imageX; //position of left edge of image
private int imageY; //position of top edge of image
private JFrame frame;
public static void main(String[] args)
{
DisplayExample example = new DisplayExample();
example.run();
}
public DisplayExample()
{
imageX = 200;
imageY = 200;
backgroundName = "backgroundShip.jpg";
URL backgroundURL = getClass().getResource(backgroundName);
if (backgroundURL == null)
throw new RuntimeException("Unable to load: " + backgroundName);
try{backgroundImage = ImageIO.read(backgroundURL);}catch(IOException ioe){}
//load image
String fileName = "explosion.png";
URL url = getClass().getResource(fileName);
if (url == null)
throw new RuntimeException("Unable to load: " + fileName);
//image = new ImageIcon(url).getImage();
try{image = ImageIO.read(url);}catch(IOException ioe){}
System.out.println(image instanceof BufferedImage);
setPreferredSize(new Dimension(1040,500)); //set size of drawing region
//need for keyboard input
setFocusable(true); //indicates that WorldDisp can process key presses
frame = new JFrame();
frame.getContentPane().add(this);
frame.pack();
frame.setVisible(true);
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
if(backgroundImage != null)
g.drawImage(backgroundImage,0,0,getWidth(), getHeight(), null);
g.drawImage(image, imageX, imageY, this);
}
public void run()
{
while(true)
{
imageY+=1;
repaint();
try{Thread.sleep(100);}catch(Exception e){}
}
}
}
So I took your code, added my own images and it runs fine for me.
Having said that, there are some areas you can improve:
You're running the risk of either blocking the Event Dispatching Thread or introducing a thread race condition into your code with your run method. You should consider using a Swing Timer instead. See How to use Swing Timers for more details. This allows you to schedule regular callbacks which are called within the context of the EDT, making it safer to update the context of the UI
You should only ever create or modify the state of the UI from within the context of the EDT, Swing is not thread safe. See Initial Threads for more details. Swing has been known to have "issues" when the UI is not initialised within the EDT
Scaling an image is expensive, you should avoid doing so from within the paint methods, instead, scale the image and keep a reference to the result and use it when you need to paint it.
You should consider using the key bindings API over KeyListener, it will solve many of the issues associated with using KeyListener. See How to Use Key Bindings for more details.
For example...
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class DisplayExample extends JComponent {
private BufferedImage backgroundImage;
private String backgroundName;
private BufferedImage image; //image to draw
private int imageX; //position of left edge of image
private int imageY; //position of top edge of image
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
DisplayExample example = new DisplayExample();
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(example);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public DisplayExample() {
imageX = 200;
imageY = 200;
try {
backgroundImage = ImageIO.read(new File("..."));
} catch (IOException ioe) {
ioe.printStackTrace();
}
//load image
try {
image = ImageIO.read(new File("..."));
} catch (IOException ioe) {
ioe.printStackTrace();
}
//need for keyboard input
//setFocusable(true); //indicates that WorldDisp can process key presses
// Use the key bindings API instead, causes less issues
Timer timer = new Timer(100, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
imageY += 1;
repaint();
}
});
timer.start();
}
#Override
public Dimension getPreferredSize() {
return backgroundImage == null ? new Dimension(200, 200) : new Dimension(backgroundImage.getWidth(), backgroundImage.getHeight());
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
if (backgroundImage != null) {
// Scaling is expensive, don't do it here
int x = (getWidth() - backgroundImage.getWidth()) / 2;
int y = (getHeight() - backgroundImage.getHeight()) / 2;
g2d.drawImage(backgroundImage, x, y, this);
}
g2d.drawImage(image, imageX, imageY, this);
g2d.dispose();
}
}

Simple bufferedimage flickering when calling repaint

I'm trying to create a webcam view with openCV but when I repaint the saved image it flickers and the images look half gray sometimes.
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JPanel;
public class Panel extends JPanel {
BufferedImage img;
public Panel() {
super(true);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
try {
img = ImageIO.read(new File("webcam.jpg"));
} catch (IOException e) {
e.printStackTrace();
}
g.drawImage(img, 0, 0, 640, 480, this);
repaint();
}
}
Don't read your image in your paintComponent() method. Read the image in your constructor.
Also, don't call repaint() from your paintComponent() method. If you need to continuously redraw, use a Thread or a Timer.
Edit: this might need some tweaking, but it's the basic approach I'm talking about:
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JPanel;
public class Panel extends JPanel implements Runnable{
BufferedImage img;
public Panel() {
super(true);
new Thread(this).start();
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
if(img != null){
synchronized(this){
g.drawImage(img, 0, 0, 640, 480, this);
}
}
}
public void run(){
while(true){
try {
synchronized(this){
img = ImageIO.read(new File("webcam.jpg"));
}
} catch (IOException e) {
e.printStackTrace();
}
repaint();
try {
Thread.sleep((long) (1000.0/30));
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}

Print the whole program layout

I have made a Java program (JFrame based) using Netbeans,
I would like to know if it is possible to print the layout of the program
I wish to have a button and set the function to "print"
and the final layout of the frame will be printed, is it possible?
If yes, any reference source?
This will depend on what it is you hope to achieve.
You could simply print the contents of the frame to a BufferedImage. This allows you to control what you want to capture, in that you could print the content pane instead of the frame.
You could use Robot to capture the screen. This will capture what ever is on the screen at the location you are trying to capture, which might include more then just your frame...
"Print" vs "Capture"
import java.awt.EventQueue;
import java.awt.Graphics2D;
import java.awt.GridBagLayout;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.KeyStroke;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class PrintFrame {
public static void main(String[] args) {
new PrintFrame();
}
public PrintFrame() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JLabel label = new JLabel("Clap if you're happy");
final JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new GridBagLayout());
frame.add(label);
frame.setSize(200, 200);
frame.setLocationRelativeTo(null);
InputMap im = label.getInputMap(JLabel.WHEN_IN_FOCUSED_WINDOW);
ActionMap am = label.getActionMap();
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_P, KeyEvent.CTRL_DOWN_MASK), "Print");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_P, KeyEvent.CTRL_DOWN_MASK | KeyEvent.ALT_DOWN_MASK), "PrintAll");
am.put("Print", new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
try {
System.out.println("Print...");
BufferedImage img = new BufferedImage(frame.getWidth(), frame.getHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = img.createGraphics();
frame.printAll(g2d);
g2d.dispose();
ImageIO.write(img, "png", new File("Print.png"));
} catch (IOException ex) {
ex.printStackTrace();
}
}
});
am.put("PrintAll", new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
try {
System.out.println("PrintAll...");
Robot bot = new Robot();
Rectangle bounds = frame.getBounds();
bounds.x -= 2;
bounds.y -= 2;
bounds.width += 4;
bounds.height += 4;
BufferedImage img = bot.createScreenCapture(bounds);
ImageIO.write(img, "png", new File("PrintAll.png"));
} catch (Exception ex) {
ex.printStackTrace();
}
}
});
frame.setVisible(true);
}
});
}
}
Updated with better requirements
The basic requirement doesn't change a lot. You still need to capture the screen some how...
Here I've modified by "print" code to send the resulting BufferedImage to the printer. Note, I've done no checking to see if the image will actually fit, I'm sure you can work that out ;)
am.put("Print", new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
try {
System.out.println("Print...");
BufferedImage img = new BufferedImage(frame.getWidth(), frame.getHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = img.createGraphics();
frame.printAll(g2d);
g2d.dispose();
PrinterJob pj = PrinterJob.getPrinterJob();
pj.setPrintable(new FramePrintable(img));
if (pj.printDialog()) {
pj.print();
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
});
Then, you simply need some way to actually render the contents to the printer...
public class FramePrintable implements Printable {
private BufferedImage img;
public FramePrintable(BufferedImage img) {
this.img = img;
}
#Override
public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) throws PrinterException {
if (pageIndex == 0) {
Graphics2D g2d = (Graphics2D) graphics;
g2d.translate(pageFormat.getImageableX(), pageFormat.getImageableY());
double x = (pageFormat.getImageableWidth() - img.getWidth()) / 2;
double y = (pageFormat.getImageableHeight()- img.getHeight()) / 2;
g2d.drawImage(img, (int)x, (int)y, null);
}
return pageIndex == 0 ? PAGE_EXISTS : NO_SUCH_PAGE;
}
}
This is pretty much take straight from the Printing trial...
The simplest way is to use class Robot that can capture screen fragment at given coordinates. Take a look on this discussion: Java print screen program
Just send to robot the absolute coordinates of your JFrame
Try taking a screenshot and save it to a file. Then you can print the file. The following code snippet can be used to take a screenshot :
boolean captureScreenShot()
{
boolean isSuccesful = false;
Rectangle screenRect = new Rectangle(0,0,500,500);//frame absolute coordinates
BufferedImage capture;
try {
capture = new Robot().createScreenCapture(screenRect);
// screen shot image will be save at given path with name "screen.jpeg"
ImageIO.write(capture, "jpg", new File( "c:\\abc", "screen.jpeg"));
isSuccesful = true;
} catch (AWTException awte) {
awte.printStackTrace();
isSuccesful = false;
}
catch (IOException ioe) {
ioe.printStackTrace();
isSuccesful = false;
}
return isSuccesful;
}

Categories

Resources