Print jLabel's icon in a printer using a button [closed] - java

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question appears to be off-topic because it lacks sufficient information to diagnose the problem. Describe your problem in more detail or include a minimal example in the question itself.
Closed 8 years ago.
Improve this question
I have a jLabel with an Icon that I want to print in a printer (canon,hp,epson anything) using a button.
How can I do that?
Any useful code?
Code snippet?
links?
All I can see is like this:
How to print content of a label in java?
But It's not what I want.
I'm using netbeans
Thanks in advance.

Basically, the answer will depend on whether the label is displayed on the screen or not. To ensure that the label (or in fact, any component) can be printed, it must first be sized properly...
This can be done using setSize and feeding it getPreferredSize at the very basic level.
The next step is passing using the components printAll method (or print method depending on your needs) which is better suited for...printing...as it disables double buffering and won't produce nasty exceptions when it's not attached to a native peer...
Example printed as preferred size...
Example printed to fill available area...
Now the example uses the printComponentToFile method, but you'll want to use the printComponent method for actually printing it a printer, the first is useful for doing things like page previews and screen dumps...
import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
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.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
public class PrintALabel {
public static void main(String[] args) {
try {
JLabel label = new JLabel(
"This is a test",
new ImageIcon("path/to/image"),
JLabel.CENTER);
printComponentToFile(label, true);
printComponentToFile(label, false);
} catch (PrinterException exp) {
exp.printStackTrace();
}
}
public static void printComponent(JComponent comp, boolean fill) throws PrinterException {
PrinterJob pjob = PrinterJob.getPrinterJob();
PageFormat pf = pjob.defaultPage();
pf.setOrientation(PageFormat.LANDSCAPE);
PageFormat postformat = pjob.pageDialog(pf);
if (pf != postformat) {
//Set print component
pjob.setPrintable(new ComponentPrinter(comp, fill), postformat);
if (pjob.printDialog()) {
pjob.print();
}
}
}
public static void printComponentToFile(Component comp, boolean fill) 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()));
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());
double height = (int) Math.floor(format.getImageableHeight());
if (!fill) {
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));
if (comp.getParent() == null) {
comp.addNotify();
}
comp.validate();
comp.doLayout();
comp.printAll(g2);
if (comp.getParent() != null) {
comp.removeNotify();
}
return Printable.PAGE_EXISTS;
}
}
}

Related

How can I create a 'cooldown rectangle' effect in Java? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
Edit: In order to make this a little more specific, I wanted to know how to create the timeout effect as seen in the image. I know about painting an image and such, but I did not understand the logic behind the timeout effect, hence the question.
I've been doing some research on this 'cooldown rectangle' effect and it seems to be doable in many other languages, but so far I haven't seen many solutions in regards to Java. Essentially I would like to create a function that does an effect like this over an image.
I already know the basics of overlaying an image, and I've come across a class which does something like this but in the more commonly known 'circular' version.
I did find this tutorial which explained how to create the effect above using GameMaker. But I'm not sure how to transfer that knowledge to Java.
Any help would be appreciated, thanks.
So, what you need is...
Some way to load an image
Some way to paint the image
Some way to paint a timeout effect over the image
Some way to update the UI at a regular interval based, calculating the amount of time remaining and updating the UI
Maybe start with:
Reading/Loading an Image
Painting in AWT and Swing and Performing Custom Painting
2D Graphics
Concurrency in Swing and How to use Swing Timers
For example...
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
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 {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
TimeOutPane tp = new TimeOutPane();
tp.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
tp.executeTimeout();
}
});
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(tp);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
} catch (IOException ex) {
ex.printStackTrace();
}
}
});
}
public class TimeOutPane extends JPanel {
private BufferedImage background;
private float progress = 0;
private long startedAt;
private int timeout = 5000;
private Timer timer;
public TimeOutPane() throws IOException {
background = ImageIO.read(new File("/Volumes/Disk02/Dropbox/Ponies/url.png"));
}
public void setTimeout(int timeout) {
this.timeout = timeout;
}
public int getTimeout() {
return timeout;
}
public void setProgress(float progress) {
this.progress = progress;
repaint();
}
public float getProgress() {
return progress;
}
public void executeTimeout() {
if (timer == null) {
timer = new Timer(40, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
long diff = System.currentTimeMillis() - startedAt;
float progress = diff / (float) timeout;
if (diff >= timeout) {
progress = 1f;
timer.stop();
}
setProgress(progress);
}
});
} else if (timer.isRunning()) {
timer.stop();
}
startedAt = System.currentTimeMillis();
timer.start();
}
#Override
public Dimension getPreferredSize() {
return background == null ? new Dimension(200, 200) : new Dimension(background.getWidth(), background.getHeight());
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (background != null) {
Graphics2D g2d = (Graphics2D) g.create();
applyQualityRenderingHints(g2d);
int x = (getWidth() - background.getWidth()) / 2;
int y = (getHeight() - background.getHeight()) / 2;
g2d.drawImage(background, x, y, this);
g2d.setComposite(AlphaComposite.SrcOver.derive(0.5f));
g2d.setColor(Color.BLACK);
int radius = Math.max(getWidth(), getHeight()) / 2;
g2d.fillArc(-radius, -radius, radius * 4, radius * 4, 90, (int) (360f * (1f - progress)));
g2d.dispose();
}
}
public void applyQualityRenderingHints(Graphics2D g2d) {
g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
}
}
}

SplashScreen java change alpha

I am looping through a few png's to create an animation for a java splashscreen.
I start the animation using this
java -splash:images/anim.png SplashDemo
and use the pngs inside the class . You can find the class here- http://pastebin.com/UWm25QfY
My only problem is whatever alpha I choose to start the animation using anim.png is final and is being overwritten for all the pngs later
I tried the AlphaComposite.Clear,Src,SrcOver but nothing worked. If I load a png iniatially with 0 opacity then the entire animation disappears. Could anyone tell me how to get rid of this?
So, the problem you are facing has to do with the fact that the Graphics context you are painting is never actually "cleaned" or "rest" between updates. Which is a pain, I know, but there it is.
About the only choice you have is to actually reset the output on each cycle, before you paint the next image.
Lucky for use, SplashScreen actually provides the URL to background image. This allows us to load the image ourselves and repaint onto the surface as we need.
You should also make all best efforts to restore the Graphics context to the state you found it (except for what ever you painted on it of course). This can be eaisly done by making a copy of the graphics state before you paint to it...
Graphics2D g2d = (Graphics2D)g.create();
// Do you're painting here...
// Release the state when you're done.
g2d.dispose();
import java.awt.AlphaComposite;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Image;
import java.awt.SplashScreen;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
public class SplashScreen100 extends Frame implements ActionListener {
static ArrayList<Image> imgs;
private static final long serialVersionUID = 1L;
private BufferedImage background;
protected void renderSplashFrame(Graphics2D g, Image bg) {
// Get the splash screen size...
Dimension size = SplashScreen.getSplashScreen().getSize();
int width = size.width;
int height = size.height;
// Center the image within the splash screen
int x = (width - bg.getWidth(null)) / 2;
int y = (height - bg.getHeight(null)) / 2;
Graphics2D g2d = (Graphics2D) g.create();
// Draw the background
g2d.drawImage(background, 0, 0, null);
// Apply alpha composite
g2d.setComposite(AlphaComposite.SrcOver.derive(0.5f));
// Draw the image...
g2d.drawImage(bg, x, y, null);
g2d.dispose();
}
public SplashScreen100() {
super("SplashScreen demo");
final SplashScreen splash = SplashScreen.getSplashScreen();
if (splash == null) {
System.out.println("SplashScreen.getSplashScreen() returned null");
return;
}
Graphics2D g = splash.createGraphics();
if (g == null) {
System.out.println("g is null");
return;
}
try {
background = ImageIO.read(splash.getImageURL());
for (Image img : imgs) {
renderSplashFrame(g, img);
splash.update();
// I put this in to slow the updates down...
try {
Thread.sleep(250);
} catch (InterruptedException ex) {
Logger.getLogger(SplashScreen100.class.getName()).log(Level.SEVERE, null, ex);
}
}
} catch (IOException exp) {
exp.printStackTrace();
}
splash.close();
}
public void actionPerformed(ActionEvent ae) {
System.exit(0);
}
public static void main(String args[]) {
System.setProperty("sun.java2d.opengl", "True");
GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice device = env.getDefaultScreenDevice();
GraphicsConfiguration config = device.getDefaultConfiguration();
imgs = new ArrayList<Image>();
for (File file : new File("\path\to\images").listFiles()) {
if (file.getName().toLowerCase().endsWith(".png")) {
try {
Image buffy = ImageIO.read(file);
imgs.add(buffy);
} catch (IOException e) {
e.printStackTrace();
}
}
}
SplashScreen100 test = new SplashScreen100();
}
}
Updated with a different approach
Basically, as the size of the image increases, the speed of the update decreases. Instead, I would simply create your own so you can better control the update process.
This uses an a JWindow as the base window and a customised JPanel as the main display.
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsEnvironment;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import static splashscreen.MySplashScreen.createCompatibleImage;
import static splashscreen.MySplashScreen.getGraphicsConfiguration;
public class DifferentSplashScreen {
public static void main(String[] args) {
new DifferentSplashScreen();
}
public DifferentSplashScreen() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JWindow frame = new JWindow();
frame.setAlwaysOnTop(true);
frame.setLayout(new BorderLayout());
frame.add(new SplashPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class SplashPane extends JPanel {
private BufferedImage background;
private List<BufferedImage> frames;
private int frameIndex;
private BufferedImage currentFrame;
public SplashPane() {
try {
background = ImageIO.read(new File("C:\\Users\\shane\\Dropbox\\MegaTokyo\\2005-09-29-3957.jpeg"));
frames = new ArrayList<>(40);
List<BufferedImage> images = new ArrayList<>(20);
for (int index = 0; index < 20; index++) {
try {
BufferedImage buffy = ImageIO.read(new File(index + ".png"));
images.add(createCompatibleImage(buffy));
} catch (IOException e) {
e.printStackTrace();
}
}
frames.addAll(images);
Collections.reverse(images);
frames.addAll(images);
} catch (IOException ex) {
ex.printStackTrace();
}
final Timer timer = new Timer(40, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (frameIndex >= frames.size()) {
frameIndex = 0;
}
currentFrame = frames.get(frameIndex);
frameIndex++;
repaint();
}
});
timer.start();
}
#Override
public Dimension getPreferredSize() {
return background == null ? new Dimension(200, 200) : new Dimension(background.getWidth(), background.getHeight());
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (background != null) {
Graphics2D g2d = (Graphics2D) g.create();
int x = (getWidth() - background.getWidth()) / 2;
int y = (getHeight() - background.getHeight()) / 2;
g2d.drawImage(background, x, y, this);
if (currentFrame != null) {
x = (getWidth() - currentFrame.getWidth()) / 2;
y = (getHeight() - currentFrame.getHeight()) / 2;
g2d.drawImage(currentFrame, x, y, this);
}
g2d.dispose();
}
}
}
public static GraphicsConfiguration getGraphicsConfiguration() {
return GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration();
}
public static BufferedImage createCompatibleImage(BufferedImage master) {
BufferedImage img = createCompatibleImage(master, master.getWidth(), master.getHeight());
Graphics2D g2d = img.createGraphics();
g2d.drawImage(master, 0, 0, null);
g2d.dispose();
return img;
}
public static BufferedImage createCompatibleImage(BufferedImage image,
int width, int height) {
return getGraphicsConfiguration().createCompatibleImage(width, height, image.getTransparency());
}
}
It also converts all the images to "device compatiable" images, meaning they should render faster as their color pallette's don't need to be converted on the fly.
The background image was 1563x1250 and the face images are 300x300 (with varying alpha levels).
Use this example, I got a steadily update without issue, using the same images with the SplashScreen, it was pretty horrible...

How to print a JPanel with swing components?

I am trying to print a JPanel using java.awt.print.I want to print out a JPanel.I have tried the following code which consists of only one button.When printed it appears on the left corner of the page,but I need to print it in the original position as it appears on the screen.Is there way to set bounds to give an exact position?
enter code here
import java.awt.*;
import java.awt.print.*;
import javax.swing.*;
import java.awt.event.*;
public class PrintButton extends JPanel implements
Printable, ActionListener {
JButton ok = new JButton("OK");
public PrintButton() {
ok.addActionListener(this);
this.setPreferredSize(new Dimension(400, 400));
this.add(ok);
JFrame frame = new JFrame("Print");
frame.getContentPane().add(this);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
new PrintButton();
}
public void actionPerformed(ActionEvent e) {
PrinterJob printJob = PrinterJob.getPrinterJob();
printJob.setPrintable(this);
if (printJob.printDialog()) {
try {
printJob.print();
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
}
public int print(Graphics g, PageFormat pf, int index) throws
PrinterException {
Graphics2D g2 = (Graphics2D) g;
if (index >= 1) {
return Printable.NO_SUCH_PAGE;
} else {
ok.printAll(g2);
return Printable.PAGE_EXISTS;
}
}
}
In your print method, you are only printing the button:
ok.printAll(g2);
To print the JPanel, you should call the printAll method of that JPanel:
this.printAll(g2);
If you want to be sure the panel fits on the page, you'll want to scale it using a Graphics2D transformation, based on the page size passed to you in the PageFormat object.
AffineTransform originalTransform = g2.getTransform();
double scaleX = pf.getImageableWidth() / this.getWidth();
double scaleY = pf.getImageableHeight() / this.getHeight();
// Maintain aspect ratio
double scale = Math.min(scaleX, scaleY);
g2.translate(pf.getImageableX(), pf.getImageableY());
g2.scale(scale, scale);
this.printAll(g2);
g2.setTransform(originalTransform);
Note: I haven't actually tested this.

Image.getScaledInstance() changes the grayscale level

I have a JTable and need to repaint very frequently each cell, where table's cells illustrate gray-scale images. Usually images need to be scaled for painting to fit painted area. I have two implementations inside JComponent's method paintComponent(Graphics g) :
Create scaled image Image.getScaledInstance(), and then draw it using Graphics.
Let Graphics to scale the image "on the fly";
The first method works faster, and requires less CPU. But it changes the colors (gray level) of images. The image below illustrates the issue. First method (wrong colors) on the left, and the second method (true colors) on the right.
Question: Why this happens and how to resolve it? Alternatively, any other solution will be much appreciated.
Note: in this code example I don't actually scale the images, but calling Image.getScaledInstance() still changes the image values.
The code:
class CellImage extends JComponent {
final boolean rescale_img;
final byte value;
CellImage(boolean flag, byte v) {
rescale_img = flag;
value = v;
}
#Override
public void paintComponent(Graphics g) {
Rectangle r = g.getClipBounds();
BufferedImage image = new BufferedImage(r.width, r.height, BufferedImage.TYPE_BYTE_GRAY);
byte[] bytes = ((DataBufferByte) image.getRaster().getDataBuffer()).getData();
Arrays.fill(bytes, value);
if (rescale_img){
Image scaled = image.getScaledInstance(r.width, r.height, Image.SCALE_REPLICATE);
g.drawImage(scaled, 0, 0, null);
} else {
g.drawImage(image, 0, 0, null);
}
}
}
If required, please see below the whole SSCCE:
package book_test_paint;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferByte;
import java.util.Arrays;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableCellRenderer;
class CellImage extends JComponent {
final boolean rescale_img;
final byte value;
CellImage(boolean flag, byte v) {
rescale_img = flag;
value = v;
}
#Override
public void paintComponent(Graphics g) {
Rectangle r = g.getClipBounds();
BufferedImage image = new BufferedImage(r.width, r.height, BufferedImage.TYPE_BYTE_GRAY);
byte[] bytes = ((DataBufferByte) image.getRaster().getDataBuffer()).getData();
Arrays.fill(bytes, value);
if (rescale_img){
Image scaled = image.getScaledInstance(r.width, r.height, Image.SCALE_REPLICATE);
g.drawImage(scaled, 0, 0, null);
} else {
g.drawImage(image, 0, 0, null);
}
}
}
class CellText extends JComponent {
final String str;
CellText(String s){
str = s;
}
#Override
public void paintComponent(Graphics g) {
Rectangle r = g.getClipBounds();
g.setColor(Color.BLACK);
g.fill3DRect(0, 0, r.width, r.height, true);
g.setColor(Color.WHITE);
((Graphics2D) g).drawString(str, 0.1f * r.width, 0.9f * r.height);
}
}
class MyTableModel extends DefaultTableModel {
final int nrows = 17;
#Override
public int getRowCount() {
return nrows;
}
#Override
public int getColumnCount() {
return 3;
}
#Override
public Object getValueAt(int row, int column) {
Object obj = null;
// The value below represents the desired
// gray scale of the image in range [0, 255]
int val = (int)Math.min(255, row * 256.0 / (nrows - 1));
switch (column) {
case 0:
obj = new CellImage(true, (byte)val);
break;
case 1:
obj = new CellText("" + val);
break;
case 2:
obj = new CellImage(false, (byte)val);
break;
}
return obj;
}
}
public class Image_Scaling extends JTable {
public Image_Scaling(JPanel panel) {
setModel(new MyTableModel());
setRowHeight(25);
getColumnModel().getColumn(0).setPreferredWidth(200);
getColumnModel().getColumn(1).setPreferredWidth(40);
getColumnModel().getColumn(2).setPreferredWidth(200);
JTableHeader header = getTableHeader();
header.getColumnModel().getColumn(0).setHeaderValue("with getScaledInstance()");
header.getColumnModel().getColumn(1).setHeaderValue("gray");
header.getColumnModel().getColumn(2).setHeaderValue("without getScaledInstance()");
panel.setLayout(new BorderLayout());
panel.add(header, BorderLayout.NORTH);
panel.add(this, BorderLayout.CENTER);
}
#Override
public Component prepareRenderer(TableCellRenderer renderer, int row, int column) {
return (Component) dataModel.getValueAt(row, column);
}
public static void main(String[] args) {
JPanel panel = new JPanel(new BorderLayout());
final Image_Scaling table = new Image_Scaling(panel);
final JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(panel, BorderLayout.CENTER);
frame.pack();
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
frame.setVisible(true);
}
});
}
}

Reverse Java Graphics2D scaled and rotated coordinates

I use Graphics2D in Java to scale and rotate the picture I draw. I now want to be able to tell what the original coordinates were when I click on a certain point in the picture. So given the rotated and scaled coordinates I want to calculate the original ones. Is there a simple way to do this?
If you keep a copy of the AffineTransform you use when you paint the image, you can use
AffineTransform.inverseTransform(Point2D ptSrc, Point2D ptDst)
to transform a device space coordinate back to user space
Edit: If you capture the current transform of the Graphics2D while painting, beware of the Graphics2D being re-used for multiple lightweight children of the same window/panel, because then the transform will be relative to the parent component but the mouse coordinates will be relative to the child. You need to capture the changes you make to the transform not its final value. Example:
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.awt.geom.AffineTransform;
import java.awt.geom.NoninvertibleTransformException;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JComponent;
import javax.swing.JFrame;
public class Main {
public static void main(String[] args) throws MalformedURLException, IOException {
JFrame frame = new JFrame();
Box box = new Box(BoxLayout.Y_AXIS);
BufferedImage image = ImageIO.read(new URL("http://sstatic.net/so/img/logo.png"));
AffineTransform xfrm1 = AffineTransform.getScaleInstance(0.95, 1.25);
xfrm1.rotate(-0.3);
box.add(new ImageView(image, xfrm1));
AffineTransform xfrm2 = AffineTransform.getShearInstance(0.1, 0.2);
xfrm2.scale(1.3, 0.9);
box.add(new ImageView(image, xfrm2));
frame.add(box);
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
#SuppressWarnings("serial")
class ImageView extends JComponent {
#Override
public void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
try {
paintXfrm = g2d.getTransform();
paintXfrm.invert();
g2d.translate(getWidth() / 2, getHeight() / 2);
g2d.transform(xfrm);
g2d.translate(image.getWidth() * -0.5, image.getHeight() * -0.5);
paintXfrm.concatenate(g2d.getTransform());
g2d.drawImage(image, 0, 0, this);
} catch (NoninvertibleTransformException ex) {
ex.printStackTrace();
}
}
#Override
public Dimension getPreferredSize() {
return new Dimension(image.getWidth() * 2, image.getHeight() * 2);
}
ImageView(final BufferedImage image, final AffineTransform xfrm) {
this.canvas = image.createGraphics();
canvas.setColor(Color.BLACK);
canvas.setStroke(new BasicStroke(3.0f));
this.image = image;
this.xfrm = xfrm;
addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
try {
mouseDownCoord = e.getPoint();
paintXfrm.inverseTransform(mouseDownCoord, mouseDownCoord);
} catch (NoninvertibleTransformException ex) {
}
}
#Override
public void mouseExited(MouseEvent e) {
mouseDownCoord = null;
}
});
addMouseMotionListener(new MouseMotionAdapter() {
#Override
public void mouseDragged(MouseEvent e) {
Point p = e.getPoint();
try {
paintXfrm.inverseTransform(p, p);
if (mouseDownCoord != null) {
canvas.drawLine(mouseDownCoord.x, mouseDownCoord.y, p.x, p.y);
for (Component sibling: getParent().getComponents()) {
sibling.repaint();
}
}
mouseDownCoord = p;
} catch (NoninvertibleTransformException ex) {
ex.printStackTrace();
}
}
});
}
private Graphics2D canvas;
private BufferedImage image;
private AffineTransform xfrm;
private AffineTransform paintXfrm;
private Point mouseDownCoord;
}
It's not clear exactly how you're rotating and scaling. But you're probably using an AffineTransform. Fortunately, there's a createInverse() method and a inverseTransform() method.
So your code might be
AffineTransform transform = AffineTransform.rotate(theta);
transform.scale(sx, sy);
Then to invert, you can say
Point2D pointInOrigCoords = transform.inverseTransform(clickPoint,null);
Its not so hard ;-)
When you repaint the Component save the AffineTransform after the transforming with g2.getTransform()
Then call the function invert() on it
In the mouseClicked() event us the following code:
Point2D p= trans.transform(new Point2D.Double(evt.getX(), evt.getY()), null);
System.out.println("click x="+p.getX()+" y="+p.getY());
Thats it!

Categories