Setting print size of a jLabel and put a jRadiobutton on the print
I have a jLabel with an Icon that I should print. However, I can't get the jLabel's icon to full size.
Here's some of the code that I think that it is affecting the print size.
public static void printComponentToFile(Component comp, boolean fill) throws PrinterException {
Paper paper = new Paper();
paper.setSize(8.3 * 72, 11.7 * 72); //here
paper.setImageableArea(18, 18, 100, 300); //and here
PageFormat pf = new PageFormat();
pf.setPaper(paper);
pf.setOrientation(PageFormat.LANDSCAPE);
BufferedImage img = new BufferedImage(
(int) Math.round(pf.getWidth()),
(int) Math.round(pf.getHeight()),
BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = img.createGraphics();
g2d.setColor(Color.WHITE);
g2d.fill(new Rectangle(0, 0, img.getWidth(), img.getHeight()));
ComponentPrinter cp = new ComponentPrinter(comp, fill);
try {
cp.print(g2d, pf, 0);
} finally {
g2d.dispose();
}
try {
ImageIO.write(img, "png", new File("Page-" + (fill ? "Filled" : "") + ".png"));
} catch (IOException ex) {
ex.printStackTrace();
}
}
public static class ComponentPrinter implements Printable {
private Component comp;
private boolean fill;
public ComponentPrinter(Component comp, boolean fill) {
this.comp = comp;
this.fill = fill;
}
@Override
public int print(Graphics g, PageFormat format, int page_index) throws PrinterException {
if (page_index > 0) {
return Printable.NO_SUCH_PAGE;
}
Graphics2D g2 = (Graphics2D) g;
g2.translate(format.getImageableX(), format.getImageableY());
double width = (int) Math.floor(format.getImageableWidth()); // here too
double height = (int) Math.floor(format.getImageableHeight()); // and here
if (!fill) {
width = Math.min(width, comp.getPreferredSize().width); // here
height = Math.min(height, comp.getPreferredSize().height); // here
}
comp.setBounds(0, 0, (int) Math.floor(width), (int) Math.floor(height));
if (comp.getParent() == null) {
comp.addNotify();
}
comp.validate();
comp.doLayout();
comp.printAll(g2);
if (comp.getParent() != null) {
comp.removeNotify();
}
return Printable.PAGE_EXISTS;
}
}
So what should I change with those? Also, how can I put a radiobutton on the printing process? It's because I want to print the radiobutton altogether with the label.
This is how I print a label using a button:
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
try {
printComponent(jLabel2, false);
} catch (PrinterException ex) {
Logger.getLogger(MappingScreen.class.getName()).log(Level.SEVERE, null, ex);
}
}
Can I make it like this?:
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
try {
printComponent(jLabel2, false);
printComponent(jRadioBtn1, false); //change
} catch (PrinterException ex) {
Logger.getLogger(M.class.getName()).log(Level.SEVERE, null, ex);
}
}
UPDATE:
I think I have to add something here to print another component:
public static void main(String args[]) {
try {
JLabel label = new JLabel(
"This is a test",
new ImageIcon("/adv/mapp.jpg"),
JLabel.CENTER);
printComponentToFile(label, true);
printComponentToFile(label, false);
} catch (PrinterException exp) {
exp.printStackTrace();
}
Please help. Thanks
Solution 1:
So, based on the concept presented in Printing a JFrame and its components, I've been able to produce these two examples...
Which used the following JPanel
as the base component...
public static class PrintForm extends JPanel {
public PrintForm() {
setLayout(new GridBagLayout());
JLabel label = new JLabel("This is a label");
label.setVerticalTextPosition(JLabel.BOTTOM);
label.setHorizontalTextPosition(JLabel.CENTER);
try {
label.setIcon(new ImageIcon(ImageIO.read(new File("C:\\hold\\thumbnails\\_cg_1009___Afraid___by_Serena_Clearwater.png"))));
} catch (IOException ex) {
ex.printStackTrace();
}
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.weightx = 1;
gbc.weighty = 1;
add(label, gbc);
JRadioButton rb = new JRadioButton("Open to suggestions");
rb.setSelected(true);
gbc.gridy++;
gbc.weightx = 1;
gbc.fill = GridBagConstraints.NONE;
add(rb, gbc);
}
}
And based on the concept presented in Fit/Scale JComponent to page being printed I was able to take an image of 7680x4800 and scale it down to print within an area of 842x598.
Now note. JLabel
DOES NOT support scaling. If your image does not fit within the available space, you are going to have to scale it yourself some how. The following solution scales the entire component, having said that, with a little bit of clever re-arranging, it would be possible to make the TestPane
scale it's image instead and use the above example instead...
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.awt.print.PageFormat;
import java.awt.print.Paper;
import java.awt.print.Printable;
import java.awt.print.PrinterException;
import java.awt.print.PrinterJob;
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.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class ScalablePrintingTest {
public static void main(String[] args) {
new ScalablePrintingTest();
}
public ScalablePrintingTest() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
final TestPane imagePane = new TestPane();
JButton print = new JButton("Print");
print.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
try {
//printComponent(imagePane);
printComponentToFile(imagePane);
} catch (PrinterException ex) {
ex.printStackTrace();
}
}
});
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(imagePane);
frame.add(print, BorderLayout.SOUTH);
frame.setSize(200, 200);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private BufferedImage bg;
public TestPane() {
try {
bg = ImageIO.read(new File("/path/to/a/image"));
} catch (IOException ex) {
ex.printStackTrace();
}
}
@Override
public Dimension getPreferredSize() {
return bg == null ? new Dimension(200, 200) : new Dimension(bg.getWidth(), bg.getHeight());
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
if (bg != null) {
int x = (getWidth() - bg.getWidth()) / 2;
int y = (getHeight() - bg.getHeight()) / 2;
g2d.drawImage(bg, x, y, this);
}
g2d.dispose();
}
}
public void printComponent(Component comp) {
PrinterJob pj = PrinterJob.getPrinterJob();
pj.setJobName(" Print Component ");
pj.setPrintable(new ComponentPrintable(comp));
if (!pj.printDialog()) {
return;
}
try {
pj.print();
} catch (PrinterException ex) {
System.out.println(ex);
}
}
public static void printComponentToFile(Component comp) throws PrinterException {
Paper paper = new Paper();
paper.setSize(8.3 * 72, 11.7 * 72);
paper.setImageableArea(18, 18, 559, 783);
PageFormat pf = new PageFormat();
pf.setPaper(paper);
pf.setOrientation(PageFormat.LANDSCAPE);
BufferedImage img = new BufferedImage(
(int) Math.round(pf.getWidth()),
(int) Math.round(pf.getHeight()),
BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = img.createGraphics();
g2d.setColor(Color.WHITE);
g2d.fill(new Rectangle(0, 0, img.getWidth(), img.getHeight()));
ComponentPrintable cp = new ComponentPrintable(comp);
try {
cp.print(g2d, pf, 0);
} finally {
g2d.dispose();
}
try {
ImageIO.write(img, "png", new File("Page-Scaled.png"));
} catch (IOException ex) {
ex.printStackTrace();
}
}
public static class ComponentPrintable implements Printable {
private Component comp;
private ComponentPrintable(Component comp) {
this.comp = comp;
}
@Override
public int print(Graphics g, PageFormat pf, int pageNumber)
throws PrinterException {
// TODO Auto-generated method stub
if (pageNumber > 0) {
return Printable.NO_SUCH_PAGE;
}
// Get the preferred size ofthe component...
Dimension compSize = comp.getPreferredSize();
// Make sure we size to the preferred size
comp.setSize(compSize);
// Get the the print size
Dimension printSize = new Dimension();
printSize.setSize(pf.getImageableWidth(), pf.getImageableHeight());
// Calculate the scale factor
double scaleFactor = getScaleFactorToFit(compSize, printSize);
// Don't want to scale up, only want to scale down
if (scaleFactor > 1d) {
scaleFactor = 1d;
}
// Calcaulte the scaled size...
double scaleWidth = compSize.width * scaleFactor;
double scaleHeight = compSize.height * scaleFactor;
// Create a clone of the graphics context. This allows us to manipulate
// the graphics context without begin worried about what effects
// it might have once we're finished
Graphics2D g2 = (Graphics2D) g.create();
// Calculate the x/y position of the component, this will center
// the result on the page if it can
double x = ((pf.getImageableWidth() - scaleWidth) / 2d) + pf.getImageableX();
double y = ((pf.getImageableHeight() - scaleHeight) / 2d) + pf.getImageableY();
// Create a new AffineTransformation
AffineTransform at = new AffineTransform();
// Translate the offset to out "center" of page
at.translate(x, y);
// Set the scaling
at.scale(scaleFactor, scaleFactor);
// Apply the transformation
g2.transform(at);
// Print the component
comp.printAll(g2);
// Dispose of the graphics context, freeing up memory and discarding
// our changes
g2.dispose();
comp.revalidate();
return Printable.PAGE_EXISTS;
}
}
public static double getScaleFactorToFit(Dimension original, Dimension toFit) {
double dScale = 1d;
if (original != null && toFit != null) {
double dScaleWidth = getScaleFactor(original.width, toFit.width);
double dScaleHeight = getScaleFactor(original.height, toFit.height);
dScale = Math.min(dScaleHeight, dScaleWidth);
}
return dScale;
}
public static double getScaleFactor(int iMasterSize, int iTargetSize) {
double dScale = 1;
if (iMasterSize > iTargetSize) {
dScale = (double) iTargetSize / (double) iMasterSize;
} else {
dScale = (double) iTargetSize / (double) iMasterSize;
}
return dScale;
}
}
Solution 2:
I was going to update my previous answer, but it's been accepted...
This example basically combines the solutions presented in Fit/Scale JComponent to page being printed and Printing a JFrame and its components and demonstrates the difference between scaling the component when it's printed as apposed to have the component capable of scaling itself...
It creates a interface
chain of the Printable
s, which I hope will help clear up any confusion...well, less then there was...
So starting with...
The panel on the left is static, that is, the image is not scaled by the component. The panel on the right is dynamic, that is, the component will scale the image as the size of the component is changed.
The static panel when printed using the scaled approach. You will note that both the label and radio button have been scaled as well
Compared to the dynamic panel when using the filled approach. You will note that the label and radio button are not scaled, but remain at there normal size, but the background image is scaled instead...
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.awt.print.PageFormat;
import java.awt.print.Paper;
import java.awt.print.Printable;
import java.awt.print.PrinterException;
import java.awt.print.PrinterJob;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JScrollPane;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class PrintComponentTest {
public static void main(String[] args) {
new PrintComponentTest();
}
public PrintComponentTest() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private StaticImagePane staticImagePane;
private DynamicImagePane dynamicImagePane;
public TestPane() {
JPanel content = new JPanel(new GridLayout());
content.add(new JScrollPane(preparePane(staticImagePane = new StaticImagePane())));
content.add(preparePane(dynamicImagePane = new DynamicImagePane()));
setLayout(new BorderLayout());
add(content);
JPanel options = new JPanel();
JButton normal = new JButton("Print");
normal.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
try {
printComponentToFile(new FillableCompentPrintable(staticImagePane, false), new File("Static-Normal.png"));
printComponentToFile(new FillableCompentPrintable(staticImagePane, true), new File("Static-Filled.png"));
printComponentToFile(new ScalableCompentPrintable(staticImagePane), new File("Static-Scaled.png"));
printComponentToFile(new FillableCompentPrintable(dynamicImagePane, false), new File("Dynamic-Normal.png"));
printComponentToFile(new FillableCompentPrintable(dynamicImagePane, true), new File("Dynamic-Filled.png"));
printComponentToFile(new ScalableCompentPrintable(dynamicImagePane), new File("Dynamic-Scaled.png"));
staticImagePane.invalidate();
dynamicImagePane.invalidate();
staticImagePane.revalidate();
dynamicImagePane.revalidate();
invalidate();
revalidate();
} catch (PrinterException ex) {
ex.printStackTrace();
}
}
});
options.add(normal);
add(options, BorderLayout.SOUTH);
}
protected JPanel preparePane(JPanel panel) {
panel.setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
JLabel label = new JLabel("This is some text on a label");
label.setForeground(Color.WHITE);
panel.add(label, gbc);
JRadioButton btn = new JRadioButton("Do you agree", true);
btn.setOpaque(false);
btn.setForeground(Color.WHITE);
panel.add(btn, gbc);
return panel;
}
}
public void printComponent(ComponentPrintable printable) {
PrinterJob pj = PrinterJob.getPrinterJob();
pj.setJobName(" Print Component ");
pj.setPrintable(printable);
if (!pj.printDialog()) {
return;
}
try {
pj.print();
} catch (PrinterException ex) {
System.out.println(ex);
}
}
public static void printComponentToFile(ComponentPrintable printable, File file) throws PrinterException {
Paper paper = new Paper();
paper.setSize(8.3 * 72, 11.7 * 72);
paper.setImageableArea(18, 18, 559, 783);
PageFormat pf = new PageFormat();
pf.setPaper(paper);
pf.setOrientation(PageFormat.LANDSCAPE);
BufferedImage img = new BufferedImage(
(int) Math.round(pf.getWidth()),
(int) Math.round(pf.getHeight()),
BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = img.createGraphics();
g2d.setColor(Color.WHITE);
g2d.fill(new Rectangle(0, 0, img.getWidth(), img.getHeight()));
try {
printable.print(g2d, pf, 0);
} finally {
g2d.dispose();
}
try {
ImageIO.write(img, "png", file);
} catch (IOException ex) {
ex.printStackTrace();
}
}
public static interface ComponentPrintable extends Printable {
public Component getComponent();
}
public abstract static class AbstractComponentPrintable implements ComponentPrintable {
private final Component component;
public AbstractComponentPrintable(Component component) {
this.component = component;
}
@Override
public Component getComponent() {
return component;
}
protected void beforePrinting(Component comp) {
if (comp.getParent() == null) {
comp.addNotify();
}
comp.invalidate();
comp.revalidate();
comp.doLayout();
}
protected void afterPrinting(Component comp) {
if (comp.getParent() != null) {
comp.removeNotify();
} else {
comp.invalidate();
comp.revalidate();
}
}
@Override
public int print(Graphics g, PageFormat format, int page_index) throws PrinterException {
if (page_index > 0) {
return Printable.NO_SUCH_PAGE;
}
Graphics2D g2 = (Graphics2D) g;
printComponent(g2, format, getComponent());
return Printable.PAGE_EXISTS;
}
protected abstract void printComponent(Graphics2D g, PageFormat pf, Component comp);
}
public static class FillableCompentPrintable extends AbstractComponentPrintable {
private boolean fill;
public FillableCompentPrintable(Component component, boolean fill) {
super(component);
this.fill = fill;
}
public boolean isFill() {
return fill;
}
@Override
protected void printComponent(Graphics2D g2, PageFormat pf, Component comp) {
g2.translate(pf.getImageableX(), pf.getImageableY());
double width = (int) Math.floor(pf.getImageableWidth());
double height = (int) Math.floor(pf.getImageableHeight());
if (!isFill()) {
width = Math.min(width, comp.getPreferredSize().width);
height = Math.min(height, comp.getPreferredSize().height);
}
comp.setBounds(0, 0, (int) Math.floor(width), (int) Math.floor(height));
beforePrinting(comp);
comp.printAll(g2);
afterPrinting(comp);
// Debug purposes only...
g2.translate(-pf.getImageableX(), -pf.getImageableY());
g2.setColor(Color.RED);
g2.drawRect(0, 0, (int) pf.getWidth() - 1, (int) pf.getHeight() - 1);
}
}
public static class ScalableCompentPrintable extends AbstractComponentPrintable {
public ScalableCompentPrintable(Component component) {
super(component);
}
@Override
protected void printComponent(Graphics2D g2d, PageFormat pf, Component comp) {
// Get the preferred size ofthe component...
Dimension compSize = comp.getPreferredSize();
// Make sure we size to the preferred size
comp.setSize(compSize);
// Get the the print size
Dimension printSize = new Dimension();
printSize.setSize(pf.getImageableWidth(), pf.getImageableHeight());
// Calculate the scale factor
double scaleFactor = getScaleFactorToFit(compSize, printSize);
// Don't want to scale up, only want to scale down
if (scaleFactor > 1d) {
scaleFactor = 1d;
}
// Calcaulte the scaled size...
double scaleWidth = compSize.width * scaleFactor;
double scaleHeight = compSize.height * scaleFactor;
// Create a clone of the graphics context. This allows us to manipulate
// the graphics context without begin worried about what effects
// it might have once we're finished
Graphics2D g2 = (Graphics2D) g2d.create();
// Calculate the x/y position of the component, this will center
// the result on the page if it can
double x = ((pf.getImageableWidth() - scaleWidth) / 2d) + pf.getImageableX();
double y = ((pf.getImageableHeight() - scaleHeight) / 2d) + pf.getImageableY();
// Create a new AffineTransformation
AffineTransform at = new AffineTransform();
// Translate the offset to out "center" of page
at.translate(x, y);
// Set the scaling
at.scale(scaleFactor, scaleFactor);
// Apply the transformation
g2.transform(at);
// Print the component
beforePrinting(comp);
comp.printAll(g2);
afterPrinting(comp);
// Dispose of the graphics context, freeing up memory and discarding
// our changes
g2.dispose();
// Debug purposes only...
g2d.setColor(Color.RED);
g2d.drawRect(0, 0, (int) pf.getWidth() - 1, (int) pf.getHeight() - 1);
}
public static double getScaleFactorToFit(Dimension original, Dimension toFit) {
double dScale = 1d;
if (original != null && toFit != null) {
double dScaleWidth = getScaleFactor(original.width, toFit.width);
double dScaleHeight = getScaleFactor(original.height, toFit.height);
dScale = Math.min(dScaleHeight, dScaleWidth);
}
return dScale;
}
public static double getScaleFactor(int iMasterSize, int iTargetSize) {
double dScale = 1;
if (iMasterSize > iTargetSize) {
dScale = (double) iTargetSize / (double) iMasterSize;
} else {
dScale = (double) iTargetSize / (double) iMasterSize;
}
return dScale;
}
}
public class StaticImagePane extends JPanel {
private BufferedImage image;
public StaticImagePane() {
try {
setImage(ImageIO.read(new File("path\to\a\image")));
} catch (IOException ex) {
ex.printStackTrace();
}
}
public BufferedImage getImage() {
return image;
}
public void setImage(BufferedImage image) {
this.image = image;
repaint();
}
@Override
public Dimension getPreferredSize() {
BufferedImage bg = getImage();
return bg == null ? new Dimension(200, 200) : new Dimension(bg.getWidth(), bg.getHeight());
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
paintBackground(g2d);
g2d.dispose();
}
protected void paintBackground(Graphics2D g2d) {
paintBackground(g2d, getImage());
}
protected void paintBackground(Graphics2D g2d, Image bg) {
if (bg != null) {
int x = (getWidth() - bg.getWidth(this)) / 2;
int y = (getHeight() - bg.getHeight(this)) / 2;
g2d.drawImage(bg, x, y, this);
}
}
}
public class DynamicImagePane extends StaticImagePane {
private Image scaled;
public DynamicImagePane() {
try {
setImage(ImageIO.read(new File("path\to\a\image")));
} catch (IOException ex) {
ex.printStackTrace();
}
}
@Override
public void invalidate() {
super.invalidate();
if (getImage() != null) {
int width = getWidth();
int height = getHeight();
if (width > 0 && height > 0) {
// Keep the aspect ratio
if (width > height) {
width = -1;
} else if (height > width) {
height = -1;
}
scaled = getImage().getScaledInstance(width, height, Image.SCALE_SMOOTH);
}
}
}
public Image getScaledImage() {
return scaled;
}
@Override
protected void paintBackground(Graphics2D g2d) {
paintBackground(g2d, getScaledImage());
}
}
}
Note, this is just an example, there is plenty of work that needs to be done.
One issue is with the scaling, see The Perils of Image.getScaledInstance() for details and Quality of Image after resize very low -- Java for a better approach...
Solution 3:
To make it work, I changed it to something like this:
//OLD:
public void printComponent(Component comp) {
//NEW:
public void printComponent(JComponent comp, boolean fill) throws PrinterException {
PrinterJob pj = PrinterJob.getPrinterJob();
pj.setJobName(" Print Component ");
pj.setPrintable(new ComponentPrintable(comp));
if (!pj.printDialog()) {
return;
}
try {
pj.print();
} catch (PrinterException ex) {
System.out.println(ex);
}
}