I need to make a program that will open an image and later be able to draw over it. However I got stuck because it returns my graphics as null. Here is the chunk of code where the problem should be. If anything I can add the entire thing.
public void paintComponent(Graphics gd) {
// super.paintComponent(g);
super.paintComponent(gd);
//gd.drawString("This is my custom Panel!",10,20);
pencil(gd);
}
public void pencil(Graphics gd){
Graphics2D g2 = (Graphics2D)gd;
System.out.println("g2 " + g2 + "method was called");
//g2.setColor(Color.yellow);
//Line2D line = new Line2D();
g2.drawLine(x1,y1,x2,y2);
//System.out.println("pencil");
}
public void actionPerformed(ActionEvent e) {
if (e.getSource() == open){
int returnVal = fc.showOpenDialog(Lab3.this);
if (returnVal == JFileChooser.APPROVE_OPTION) {
File file = fc.getSelectedFile();
try {
img=ImageIO.read(file);
ImageIcon icon=new ImageIcon(img); // ADDED
image.setIcon(icon); // ADDED
Dimension imageSize = new Dimension(icon.getIconWidth(),icon.getIconHeight()); // ADDED
image.setPreferredSize(imageSize); // ADDED
image.add(hbar, BorderLayout.SOUTH);
image.add(vbar, BorderLayout.EAST);
image.revalidate(); // ADDED
image.repaint(); // ADDED
Graphics gd = image.getGraphics();
}
catch(IOException e1) {}
}
}
if (e.getSource() == pencil){
try{
System.out.println("g2" + g2);
//pencil();
pencil(g2);
//g2.draw(new Ellipse2D.Double(0, 100, 30, 30));
//g2.drawRectanlge(100,100,200,200);
}
catch ( Exception err1 ) {
System.out.println( err1.getMessage( ) );
}
}
I'm guessing you can't get Graphics to work
so what you need to do is get your canvas/panel/frame from swing
Canvas canvas = new Canvas();
JFrame frame = new JFrame();
frame.add(canvas);
Graphics g = canvas.getGraphics();
Related
I have problem with program in kind of slideshow. I add two arguments for this program: path to folder which include images, time after images will be repainting.
Images should draw in original size and the window adjust to that size. If some files won't be image, program should draw "ERROR" statement. Anyway, that program haven't work at all and it haven't draw any image. Anyone could tell me why it doesn't draw anything and whether Timer is good way to repaint images?
public class ImagePanel extends JPanel
{
Image img;
private int period;
private int n = 0;
private File[] files;
Timer timer;
Dimension d;
public ImagePanel(File dir, int period)
{
this.period = period;
files = dir.listFiles();
loadImage(files[n++].getPath());
timer = new Timer(period, new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
//Component component = (Component) e.getSource();
//JFrame f = (JFrame)
//SwingUtilities.windowForComponent(component);
//f.pack();
if (n < files.length)
{
loadImage(files[n].getPath());
}
else
{
repaint();
((Timer)e.getSource()).stop();
}
n++;
}
});
timer.start();
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
if (img != null)
g.drawImage(img, 0, 0, getWidth(), getHeight(), this);
}
private void loadImage(String imgFileName)
{
img = new ImageIcon(imgFileName).getImage();
int w = img.getWidth(this);
int h = img.getHeight(this);
if (w != -1 && w != 0 && h != -1 && h != 0)
{
d = new Dimension(img.getWidth(this), img.getHeight(this));
}
revalidate();
repaint();
}
#Override
public Dimension getPreferredSize()
{
return new Dimension(img.getWidth(this), img.getHeight(this));
}
public static void main(String[] args)
{
JFrame frame = new JFrame();
frame.setLayout(new GridLayout(0, 1, 0, 0));
ImagePanel panel = new ImagePanel(new File(args[0]), Integer.parseInt(args[1]) * 1000);
frame.add(panel);
//frame.getContentPane().add(panel);
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
whether Timer is good way to repaint images?
Yes, you should use a Swing Timer to schedule the animation.
Anyone could tell me why it doesn't draw anything
In your ImagePanel class you should create a method like setImage(...). This method will be invoked by the Timer code whenever you want to change the image.
Then in the setImage(...) method you need to invoke repaint() to tell the panel to repaint itself.
I have a problem using Graphics to put an image in a jPanel. I have the next code:
JFileChooser navegador = new JFileChooser();
if (navegador.showOpenDialog(null) == 0) {
try {
BufferedImage imagenAbrir = ImageIO.read(navegador.getSelectedFile());
lienzo.paintComponents(imagenAbrir.getGraphics());
} catch (IOException e) {
JOptionPane.showMessageDialog(this, "Ocurriò un error al guardar la imàgen");
}
}
The code is part of a button, the user could select an imagen from any path, but it doesn't show anything in the panel. What could be the problem?
I think you have to change you method with BufferedImage object not a Graphics object
#Override
public void actionPerformed(ActionEvent e) {
JFileChooser navegador = new JFileChooser();
if (navegador.showOpenDialog(null) == 0) {
try {
BufferedImage imagenAbrir = ImageIO.read(navegador.getSelectedFile());
//drawPan.paintComponents(imagenAbrir.getGraphics());
drawPan.drawImage(imagenAbrir);
} catch (IOException ie) {
JOptionPane.showMessageDialog(null, "Ocurriò un error al guardar la imàgen");
}
}
}
Then, if you want to draw image, create customized JPanel class on your own.
The paintCompoent method of JComponent will be invoked automatically, every time you call repaint method in your code.
final class ImagePane extends JPanel {
private static final long serialVersionUID = 1L;
private BufferedImage myImage;
public ImagePane(final BufferedImage myImage) {
this.myImage = myImage;
}
#Override
public Dimension getPreferredSize() {
return new Dimension(240, 220);
}
public void drawImage(BufferedImage img)
{
this.myImage = img;
repaint();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (myImage != null) {
Graphics2D g2d = (Graphics2D) g.create();
int x = (getWidth() - myImage.getWidth()) / 2;
int y = (getHeight() - myImage.getHeight()) / 2;
g2d.drawImage(myImage, x, y, this);
g2d.dispose();
}
}
}
Here is full source code.
public class JFileChooserTest {
static Runnable doRun = new Runnable()
{
final class ChooseAction implements ActionListener
{
final ImagePane drawPan;
ChooseAction(final ImagePane drawPan)
{
this.drawPan = drawPan;
}
#Override
public void actionPerformed(ActionEvent e) {
JFileChooser navegador = new JFileChooser();
if (navegador.showOpenDialog(null) == 0) {
try {
BufferedImage imagenAbrir = ImageIO.read(navegador.getSelectedFile());
//drawPan.paintComponents(imagenAbrir.getGraphics());
drawPan.drawImage(imagenAbrir);
} catch (IOException ie) {
JOptionPane.showMessageDialog(null, "Ocurriò un error al guardar la imàgen");
}
}
}
}
final class ImagePane extends JPanel {
private static final long serialVersionUID = 1L;
private BufferedImage myImage;
public ImagePane(final BufferedImage myImage) {
this.myImage = myImage;
}
#Override
public Dimension getPreferredSize() {
return new Dimension(240, 220);
}
public void drawImage(BufferedImage img)
{
this.myImage = img;
repaint();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (myImage != null) {
Graphics2D g2d = (Graphics2D) g.create();
int x = (getWidth() - myImage.getWidth()) / 2;
int y = (getHeight() - myImage.getHeight()) / 2;
g2d.drawImage(myImage, x, y, this);
g2d.dispose();
}
}
}
#Override
public void run() {
final JFrame frame = new JFrame();
//frame.setSize(new Dimension(300,400));
JPanel lienzo = new JPanel();
lienzo.setLayout(new BorderLayout());
ImagePane drawPan = new ImagePane(null);
JButton drawMe = new JButton("draw me");
lienzo.add(drawMe, BorderLayout.NORTH);
lienzo.add(drawPan, BorderLayout.CENTER);
frame.add(lienzo);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
drawMe.addActionListener(new ChooseAction(drawPan));
}
};
public static void main(String[] args)
{
SwingUtilities.invokeLater(doRun);
}
}
I hope this will help you.
The code is part of a button, the user could select an imagen from any path, but it doesn't show anything in the panel. What could be the problem?
Basically, this is not how custom painting works in Swing. Never call paintComponent or paintComponents yourself, it's not your responsibility.
What you want to do is paint the image to the component via its Graphics context
Take a look at Painting in AWT and Swing and Performing Custom Painting for more details about how painting works and how you're suppose to use it
Then take a look at How to use lables for a simple solution for displaying images
You can also have a look at How to set a background picture in JPanel. It demonstrates using a JLabel and custom component for displaying an image
So, Do you want add image on the panel in which some base image is displayed?
If so, there is some trick to achieve to do this.
I prepare two images on the internet ( I am afraid these are licensed images )
Then, now i have three buttons put on your class
JButton drawMe = new JButton("draw me");
JButton pickMe = new JButton("pick me");
JButton clearMe = new JButton("clear me");
I decided to let the DrawAction class reuse with three action commands that are a draw, pick and clear together.
drawMe.addActionListener(drawAct);
drawMe.setActionCommand("draw");
pickMe.addActionListener(drawAct);
pickMe.setActionCommand("pick");
clearMe.addActionListener(drawAct);
clearMe.setActionCommand("clear");
We'll see the ImagePane class again. If you want to add a image on a image, you should have a paintcomponent method inherited from JComponent whatever components you want to use.
The 'draw me' button is to set the base image after clearing all images in the image list in which array list of the bufferedimage class.
public void drawImage(BufferedImage img)
{
if (imageList.size() > 0) imageList.clear();
imageList.add(img);
repaint();
}
The 'pick me' button is the method that add a image to the image list.
public void addImage(BufferedImage imagenAbrir) {
imageList.add(imagenAbrir);
repaint();
}
The last one is clear button, flush and clear all image buffers in the image list.
public void clearImage() {
imageList.clear();
isClear = true;
repaint();
}
Here is my trick to clear image on the panel, it is accomplished by re-drawing canvas(jPanel at this time) with some specific color(gray).
The main method, paintComponent as following..
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if(isClear)
{
Graphics2D g2d = (Graphics2D) g.create();
Rectangle2D rectangle = new Rectangle2D.Double(0,0,getWidth(),getHeight());
g2d.setPaint(Color.GRAY);
g2d.fill(rectangle);
g2d.dispose();
isClear = false;
return;
}
if (imageList.size() > 0) {
BufferedImage img = null;
for(int i = 0; i < imageList.size(); i++)
{
img = imageList.get(i);
Graphics2D g2d = (Graphics2D) g.create();
int x = (getWidth() - img.getWidth()) / 2;
int y = (getHeight() - img.getHeight()) / 2;
g2d.drawImage(img, x, y, this);
g2d.dispose();
}
}
}
Finally, you read the code below how to handle action commands along with java's component,
#Override
public void actionPerformed(ActionEvent e) {
if(e.getActionCommand().equals("draw"))
{
JFileChooser navegador = new JFileChooser();
if (navegador.showOpenDialog(null) == 0) {
try {
BufferedImage imagenAbrir = ImageIO.read(navegador.getSelectedFile());
//drawPan.paintComponents(imagenAbrir.getGraphics());
drawPan.drawImage(imagenAbrir);
} catch (IOException ie) {
JOptionPane.showMessageDialog(null, "Ocurrio un error al guardar la imagen");
}
}
}
else if(e.getActionCommand().equals("pick"))
{
JFileChooser navegador = new JFileChooser();
if (navegador.showOpenDialog(null) == 0) {
try {
BufferedImage imagenAbrir = ImageIO.read(navegador.getSelectedFile());
//drawPan.paintComponents(imagenAbrir.getGraphics());
drawPan.addImage(imagenAbrir);
} catch (IOException ie) {
JOptionPane.showMessageDialog(null, "Ocurrio un error al guardar la imagen");
}
}
}
else if(e.getActionCommand().equals("clear"))
{
drawPan.clearImage();
}
}
As you see the code, picking a file is required every time you click both the pick or draw me button.
Full source code
package com.tobee.ui.test;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class JFileChooserTest {
static Runnable doRun = new Runnable()
{
final class DrawAction implements ActionListener
{
final ImagePane drawPan;
DrawAction(final ImagePane drawPan)
{
this.drawPan = drawPan;
}
#Override
public void actionPerformed(ActionEvent e) {
System.out.println(e.getActionCommand());
if(e.getActionCommand().equals("draw"))
{
JFileChooser navegador = new JFileChooser();
if (navegador.showOpenDialog(null) == 0) {
try {
BufferedImage imagenAbrir = ImageIO.read(navegador.getSelectedFile());
//drawPan.paintComponents(imagenAbrir.getGraphics());
drawPan.drawImage(imagenAbrir);
} catch (IOException ie) {
JOptionPane.showMessageDialog(null, "Ocurriò un error al guardar la imàgen");
}
}
}
else if(e.getActionCommand().equals("pick"))
{
JFileChooser navegador = new JFileChooser();
if (navegador.showOpenDialog(null) == 0) {
try {
BufferedImage imagenAbrir = ImageIO.read(navegador.getSelectedFile());
//drawPan.paintComponents(imagenAbrir.getGraphics());
drawPan.addImage(imagenAbrir);
} catch (IOException ie) {
JOptionPane.showMessageDialog(null, "Ocurriò un error al guardar la imàgen");
}
}
}
else if(e.getActionCommand().equals("clear"))
{
drawPan.clearImage();
}
}
}
final class ImagePane extends JPanel {
private static final long serialVersionUID = 1L;
private boolean isClear;
private List<BufferedImage> imageList;
public ImagePane()
{
imageList = new ArrayList<BufferedImage>();
isClear = false;
}
public void clearImage() {
imageList.clear();
isClear = true;
repaint();
}
public void addImage(BufferedImage imagenAbrir) {
imageList.add(imagenAbrir);
repaint();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(240, 220);
}
public void drawImage(BufferedImage img)
{
if (imageList.size() > 0) imageList.clear();
imageList.add(img);
repaint();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if(isClear)
{
Graphics2D g2d = (Graphics2D) g.create();
Rectangle2D rectangle = new Rectangle2D.Double(0,0,getWidth(),getHeight());
g2d.setPaint(Color.GRAY);
g2d.fill(rectangle);
g2d.dispose();
isClear = false;
return;
}
if (imageList.size() > 0) {
BufferedImage img = null;
for(int i = 0; i < imageList.size(); i++)
{
img = imageList.get(i);
Graphics2D g2d = (Graphics2D) g.create();
int x = (getWidth() - img.getWidth()) / 2;
int y = (getHeight() - img.getHeight()) / 2;
g2d.drawImage(img, x, y, this);
g2d.dispose();
}
}
}
}
#Override
public void run() {
final JFrame frame = new JFrame();
JPanel lienzo = new JPanel();
lienzo.setLayout(new BorderLayout());
JPanel optionPan = new JPanel();
ImagePane drawPan = new ImagePane();
JButton drawMe = new JButton("draw me");
JButton pickMe = new JButton("pick me");
JButton clearMe = new JButton("clear me");
DrawAction drawAct = new DrawAction(drawPan);
optionPan.add(drawMe);
optionPan.add(pickMe);
optionPan.add(clearMe);
lienzo.add(optionPan, BorderLayout.NORTH);
lienzo.add(drawPan, BorderLayout.CENTER);
frame.add(lienzo);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
drawMe.addActionListener(drawAct);
drawMe.setActionCommand("draw");
pickMe.addActionListener(drawAct);
pickMe.setActionCommand("pick");
clearMe.addActionListener(drawAct);
clearMe.setActionCommand("clear");
}
};
public static void main(String[] args)
{
SwingUtilities.invokeLater(doRun);
}
}
I have the following problems:
I don't know why my function, when displaying already rotated images, shows only one in as many jpanels as there were photos given.
Let me give an example: I load 4 images into hashmap. Then I put them into my rotate function and try to display them. I end up with 4 tabs of one rotated image.
When I'm trying to rotate twice using the same deegres as used previously (I'm using slider to take degrees) it doesn't rotate anymore but if I touch slider and move it, the function rotates normally.
I had no idea how to convert an Image type into File object thus I converted it into BufferedImage and then to File. I browsed through the Internet but could not find anything helpful.
My main's class piece of code:
JPanel panel_2e = new JPanel();
panel_2e.setOpaque(true);
panel_2e.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(EtchedBorder.RAISED, Color.GRAY, Color.DARK_GRAY), "Rotate options"));
panel_2e.setLayout(new BoxLayout(panel_2e,BoxLayout.Y_AXIS));
JSlider slider = new JSlider(JSlider.HORIZONTAL, 0, 360, 180);
slider.setMinorTickSpacing(10);
slider.setMajorTickSpacing(90);
slider.setPaintTicks(true);
slider.setPaintLabels(true);
slider.setLabelTable(slider.createStandardLabels(45));
JPanel radio_buttons_rotate=new JPanel();
radio_buttons_rotate.setLayout(new BoxLayout(radio_buttons_rotate, BoxLayout.Y_AXIS));
JCheckBox cut_frame = new JCheckBox("Cut edges");
cut_frame.setSelected(true);
cut_frame.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent e) {
if(e.getStateChange() == ItemEvent.SELECTED)
{check = true;
System.out.println("Cut-edge mode selected");}
else
{check = false;
System.out.println("Cut-edge mode deselected");}
}
});
cut_frame.setBounds(78, 41, 60, 23);
radio_buttons_rotate.add(cut_frame);
JRadioButton black_rdbutton = new JRadioButton("Black background");
black_rdbutton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
black = true;
}
});
black_rdbutton.setBounds(78, 41, 60, 23);
radio_buttons_rotate.add(black_rdbutton);
JRadioButton white_rdbutton = new JRadioButton("White background");
white_rdbutton.setSelected(true);
white_rdbutton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
black = false;
}
});
white_rdbutton.setBounds(78, 41, 60, 23);
radio_buttons_rotate.add(white_rdbutton);
ButtonGroup group_frame_rotate = new ButtonGroup();
group_frame_rotate.add(black_rdbutton);
group_frame_rotate.add(white_rdbutton);
panel_2e.add(radio_buttons_rotate);
JLabel Rotate = new JLabel();
Rotate.setText(deg+"\u00b0");
panel_2e.add(slider);
JButton btnRotate = new JButton("Rotate");
JPanel RotatePanel=new JPanel();
RotatePanel.add(Rotate);
RotatePanel.add(btnRotate);
RotatePanel.setLayout(new FlowLayout());
btnRotate.setBounds(28, 158, 89, 23);
btnRotate.setBackground(Color.DARK_GRAY);
btnRotate.setForeground(Color.WHITE);
panel_2e.add(RotatePanel);
panel_2.add(panel_2e);
slider.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent ce) {
deg=((JSlider) ce.getSource()).getValue();
Rotate.setText(deg+"\u00b0"); }
});
btnRotate.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
if(AddDirectory.all_chosen.isEmpty())
{Object[] options = {"OK"};
int n = JOptionPane.showOptionDialog(frame,
"Please choose at least 1 image to rotate.","Empty work list",
JOptionPane.PLAIN_MESSAGE,
JOptionPane.QUESTION_MESSAGE,
null,
options,
options[0]);}
else
{RotateFunction rot = new RotateFunction(AddDirectory.all_chosen);
rot.main();
BufferedImage kk = null;
Display disp= new Display(); // invoke Display class
for(File i : all_chosen_images.values()){
try{
kk = ImageIO.read(new File(i.getAbsolutePath()));
disp.createFrame(center, i, kk); //create new frame with image
}
catch (IOException es){
es.printStackTrace();
}
}
}
}
});
And here is my rotate function:
public class RotateFunction{
HashMap<JButton,File> map;
Image spiral;
RotateFunction(HashMap<JButton,File> source_of_image)
{
map = AddDirectory.all_chosen;
}
public void main(){
int counter = 0;
if (spiral == null){
for(Map.Entry<JButton, File> entry: map.entrySet()) //////Moving through hashMap
{
try {
spiral = getImage(entry.getValue().getAbsolutePath());
counter++;
System.out.println("Path of image " + counter + " : " +entry.getValue().getAbsolutePath());
if (PhotoEdit.check == true){
rotateImage(PhotoEdit.deg, null);
System.out.println("Rotating image "+counter+" by "+PhotoEdit.deg+" degrees (edge cut)");
}
else{
rotateImage1(PhotoEdit.deg, null);
System.out.println("Rotating image "+counter+" by "+PhotoEdit.deg+" degrees (bigger frame)");
}
BufferedImage tmp = toBufferedImage(spiral);
File f;
f = new File( "image.png" );
try
{
ImageIO.write( tmp, "PNG", f );
}
catch ( IOException x )
{
// Complain if there was any problem writing
// the output file.
x.printStackTrace();
}
map.put(entry.getKey(), f);
}
catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
PhotoEdit.all_chosen_images.clear();
PhotoEdit.all_chosen_images.putAll(map); //Putting HashMap with rotated images into global HashMap
System.out.println("Images have been successfully rotated");
}
}
public Image getImage(String path){
Image tempImage = null;
try
{
tempImage = Toolkit.getDefaultToolkit().getImage(path);
}
catch (Exception e)
{
System.out.println("An error occured - " + e.getMessage());
}
return tempImage;
}
////////////////////////////////////////////////////////////////////
///////////////////IMAGE ROTATION /////////////////////////////////
public void rotateImage(double degrees, ImageObserver o){
ImageIcon icon = new ImageIcon(this.spiral);
BufferedImage blankCanvas = new BufferedImage(icon.getIconWidth(), icon.getIconHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = (Graphics2D)blankCanvas.getGraphics();
g2.rotate(Math.toRadians(degrees), icon.getIconWidth()/2, icon.getIconHeight()/2);
g2.drawImage(this.spiral, 0, 0, o);
this.spiral = blankCanvas;
}
public void rotateImage1(double degrees, ImageObserver o){
double sin = Math.abs(Math.sin(Math.toRadians(degrees)));
double cos = Math.abs(Math.cos(Math.toRadians(degrees)));
ImageIcon icon = new ImageIcon(this.spiral);
int w = icon.getIconWidth();
int h = icon.getIconHeight();
int neww = (int)Math.floor(w*cos+h*sin);
int newh = (int)Math.floor(h*cos+w*sin);
BufferedImage blankCanvas = new BufferedImage(neww, newh, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = (Graphics2D)blankCanvas.getGraphics();
g2.translate((neww-w)/2, (newh-h)/2);
g2.rotate(Math.toRadians(degrees), icon.getIconWidth()/2, icon.getIconHeight()/2);
g2.drawImage(this.spiral, 0, 0, o);
this.spiral = blankCanvas;
}
//////////////////////////////////////////////////////////////////////////
public static BufferedImage toBufferedImage(Image img)
{
if (img instanceof BufferedImage)
{
return (BufferedImage) img;
}
// Create a buffered image with transparency
BufferedImage bimage = new BufferedImage(img.getWidth(null), img.getHeight(null), BufferedImage.TYPE_INT_ARGB);
// Draw the image on to the buffered image
Graphics2D bGr = bimage.createGraphics();
bGr.drawImage(img, 0, 0, null);
bGr.dispose();
// Return the buffered image
return bimage;
}
}
In the display function i have the following arguments - createFrame(JDekstopPane where_to_put_the_image, File img, BufferedImage image)
HashMap - all_chosen_images is the global HashMap storing all the images
Really hope for your help.
Aleksander
I am currently working on my personal project. The idea is to import a picture and crop it into n-pieces of bufferedimage then draw them with random sequence to a java canvas. After that save the canvas to image file. Right now iam stuck at saving the canvas and i have searching for the solutions but none of them work. Here my save procedure.
Please help, thanks in advance
private void save() {
int r = jFileChooser1.showSaveDialog(this);
File file2 = null;
if(r == jFileChooser1.APPROVE_OPTION){
file2 = jFileChooser1.getSelectedFile();
Graphics g2d = canvas.getGraphics();
BufferedImage bi = new BufferedImage(300, 300, BufferedImage.TYPE_INT_RGB);
Graphics2D g2 = bi.createGraphics();
canvas.paint(g2);
g2.dispose();
g2d.dispose();
try
{
ImageIO.write(bi, "jpg", file2);
}
catch (Exception ex) {
System.out.println("Error saving");
}
}
}
Update :
Now i get it, after using paintComponents now i can save the picture. Thanks #madProgrammer
public class CaptureImage extends javax.swing.JFrame {
MyPanel canvas;
BufferedImage[] processedImage;
public CaptureImage(BufferedImage[] proc) {
processedImage = proc;
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
private void createAndShowGUI() {
System.out.println("Created GUI on EDT? "
+ SwingUtilities.isEventDispatchThread());
JFrame f = new JFrame("Output Picture");
f.addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent e){
save();
System.exit(0);//cierra aplicacion
}
});
canvas = new MyPanel(processedImage);
f.add(canvas);
f.setSize(400, 400);
f.setVisible(true);
}
public void save() {
JFileChooser jFileChooser1 = new JFileChooser();
int r = jFileChooser1.showSaveDialog(this);
File file2 = null;
if (r == jFileChooser1.APPROVE_OPTION) {
file2 = jFileChooser1.getSelectedFile();
BufferedImage bi = new BufferedImage(300, 300, BufferedImage.TYPE_INT_RGB);
Graphics2D g2 = bi.createGraphics();
canvas.print(g2);
try {
ImageIO.write(bi, "jpg", file2);
g2.dispose();
} catch (Exception ex) {
System.out.println("Error saving");
}
}
}
}
class MyPanel extends JPanel {
private Image[] processedImage;
public MyPanel(Image[] processedImage) {
this.processedImage = processedImage;
addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
repaint();
}
});
}
public Dimension getPreferredSize() {
return new Dimension(300, 300);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
int loopj = 10;
int loopi = 10;
int l = 0;
int jPieces = 100;
int[] r = new int[jPieces];
int rand = 0;
for (int i = 0; i < r.length; i++) {
rand = (int) (Math.random() * (r.length));
if (Arrays.binarySearch(r, 0, r.length, rand) <= -1) {
r[i] = rand;
}
}
Graphics2D g2d = (Graphics2D) g;
for (int i = 0; i < loopi; i++) {
for (int j = 0; j < loopj; j++) {
g2d.drawImage(processedImage[r[l]], i * 30, j * 30, this);
l++;
}
}
}
}
There's no need to use getGraphics and you certainly shouldn't be disposing of it.
Instead of using paint, which could include double buffering, you should try using printAll
BufferedImage bi = new BufferedImage(canvas.getWidth(), canvas.getHeight(), BufferedImage.TYPE_INT_RGB);
Graphics2D g2 = bi.createGraphics();
canvas.printAll(g2);
g2.dispose();
See Component#printAll for more details.
You should also be using the size of the canvas to determine the size of the image. The above example assumes that the canvas has already been sized appropriately...
Since Java only supports single inheritance, I desire to paint directly on an instance of a JPanel that is a member of the class Panel. I grab an instance of Graphics from the member and then paint whatever I desire onto it.
How can I not inherit from JComponent or JPanel and still utilize getGraphics() for painting on this without overriding public void paintComponent(Graphics g)?
private class Panel {
private JPanel panel;
private Graphics g;
public Panel() {
panel = new JPanel();
}
public void draw() {
g = panel.getGraphics();
g.setColor(Color.CYAN);
g.draw(Some Component);
panel.repaint();
}
}
The panel is added to a JFrame that is made visible prior to calling panel.draw(). This approach is not working for me and, although I already know how to paint custom components by inheriting from JPanel and overriding public void paintComponent(Graphics g), I did not want to inherit from JPanel.
Here are some very simple examples which show how to paint outside paintComponent.
The drawing actually happens on a java.awt.image.BufferedImage, and we can do that anywhere, as long as we're on the Event Dispatch Thread. (For discussion of multithreading with Swing, see here and here.)
Then, I'm overriding paintComponent, but only to paint the image on to the panel. (I also paint a little swatch in the corner.)
This way the drawing is actually permanent, and Swing is able to repaint the panel if it needs to without causing a problem for us. We could also do something like save the image to a file easily, if we wanted to.
import javax.swing.*;
import java.awt.*;
import java.awt.image.*;
import java.awt.event.*;
/**
* Holding left-click draws, and
* right-clicking cycles the color.
*/
class PaintAnyTime {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new PaintAnyTime();
}
});
}
Color[] colors = {Color.red, Color.blue, Color.black};
int currentColor = 0;
BufferedImage img = new BufferedImage(256, 256, BufferedImage.TYPE_INT_ARGB);
Graphics2D imgG2 = img.createGraphics();
JFrame frame = new JFrame("Paint Any Time");
JPanel panel = new JPanel() {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
// Creating a copy of the Graphics
// so any reconfiguration we do on
// it doesn't interfere with what
// Swing is doing.
Graphics2D g2 = (Graphics2D) g.create();
// Drawing the image.
int w = img.getWidth();
int h = img.getHeight();
g2.drawImage(img, 0, 0, w, h, null);
// Drawing a swatch.
Color color = colors[currentColor];
g2.setColor(color);
g2.fillRect(0, 0, 16, 16);
g2.setColor(Color.black);
g2.drawRect(-1, -1, 17, 17);
// At the end, we dispose the
// Graphics copy we've created
g2.dispose();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(img.getWidth(), img.getHeight());
}
};
MouseAdapter drawer = new MouseAdapter() {
boolean rButtonDown;
Point prev;
#Override
public void mousePressed(MouseEvent e) {
if (SwingUtilities.isLeftMouseButton(e)) {
prev = e.getPoint();
}
if (SwingUtilities.isRightMouseButton(e) && !rButtonDown) {
// (This just behaves a little better
// than using the mouseClicked event.)
rButtonDown = true;
currentColor = (currentColor + 1) % colors.length;
panel.repaint();
}
}
#Override
public void mouseDragged(MouseEvent e) {
if (prev != null) {
Point next = e.getPoint();
Color color = colors[currentColor];
// We can safely paint to the
// image any time we want to.
imgG2.setColor(color);
imgG2.drawLine(prev.x, prev.y, next.x, next.y);
// We just need to repaint the
// panel to make sure the
// changes are visible
// immediately.
panel.repaint();
prev = next;
}
}
#Override
public void mouseReleased(MouseEvent e) {
if (SwingUtilities.isLeftMouseButton(e)) {
prev = null;
}
if (SwingUtilities.isRightMouseButton(e)) {
rButtonDown = false;
}
}
};
PaintAnyTime() {
// RenderingHints let you specify
// options such as antialiasing.
imgG2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
imgG2.setStroke(new BasicStroke(3));
//
panel.setBackground(Color.white);
panel.addMouseListener(drawer);
panel.addMouseMotionListener(drawer);
Cursor cursor =
Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR);
panel.setCursor(cursor);
frame.setContentPane(panel);
frame.pack();
frame.setResizable(false);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
It's also possible to set up a JLabel with an ImageIcon, although personally I don't like this method. I don't think JLabel and ImageIcon are required by their specifications to see changes we make to the image after we've passed it to the constructors.
This way also doesn't let us do stuff like painting the swatch. (For a slightly more complicated paint program, on the level of e.g. MSPaint, we'd want to have a way to select an area and draw a bounding box around it. That's another place we'd want to be able to paint directly on the panel, in addition to drawing to the image.)
import javax.swing.*;
import java.awt.*;
import java.awt.image.*;
import java.awt.event.*;
/**
* Holding left-click draws, and
* right-clicking cycles the color.
*/
class PaintAnyTime {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new PaintAnyTime();
}
});
}
Color[] colors = {Color.red, Color.blue, Color.black};
int currentColor = 0;
BufferedImage img = new BufferedImage(256, 256, BufferedImage.TYPE_INT_ARGB);
Graphics2D imgG2 = img.createGraphics();
JFrame frame = new JFrame("Paint Any Time");
JLabel label = new JLabel(new ImageIcon(img));
MouseAdapter drawer = new MouseAdapter() {
boolean rButtonDown;
Point prev;
#Override
public void mousePressed(MouseEvent e) {
if (SwingUtilities.isLeftMouseButton(e)) {
prev = e.getPoint();
}
if (SwingUtilities.isRightMouseButton(e) && !rButtonDown) {
// (This just behaves a little better
// than using the mouseClicked event.)
rButtonDown = true;
currentColor = (currentColor + 1) % colors.length;
label.repaint();
}
}
#Override
public void mouseDragged(MouseEvent e) {
if (prev != null) {
Point next = e.getPoint();
Color color = colors[currentColor];
// We can safely paint to the
// image any time we want to.
imgG2.setColor(color);
imgG2.drawLine(prev.x, prev.y, next.x, next.y);
// We just need to repaint the
// label to make sure the
// changes are visible
// immediately.
label.repaint();
prev = next;
}
}
#Override
public void mouseReleased(MouseEvent e) {
if (SwingUtilities.isLeftMouseButton(e)) {
prev = null;
}
if (SwingUtilities.isRightMouseButton(e)) {
rButtonDown = false;
}
}
};
PaintAnyTime() {
// RenderingHints let you specify
// options such as antialiasing.
imgG2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
imgG2.setStroke(new BasicStroke(3));
//
label.setPreferredSize(new Dimension(img.getWidth(), img.getHeight()));
label.setBackground(Color.white);
label.setOpaque(true);
label.addMouseListener(drawer);
label.addMouseMotionListener(drawer);
Cursor cursor =
Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR);
label.setCursor(cursor);
frame.add(label, BorderLayout.CENTER);
frame.pack();
frame.setResizable(false);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
class SomeComponent extends JComponent {
private Graphics2D g2d;
public void paintComponent(Graphics g) {
g2d = (Graphics2D) g.create();
g2d.setColor(Color.BLACK);
g2d.scale(scale, scale);
g2d.drawOval(0, 0, importance, importance);
}
public Graphics2D getG2d() {
return g2d;
}
public void setG2d(Graphics2D g2d) {
this.g2d = g2d;
}
}
then you can do the following
get the SomeComponent instance in the panel and modify it
Graphics2D x= v.getPanel().get(i).getG2d;
x.setColor(Color.BLUE);
v.getPanel().get(i).setG2d(x);
v.getPanel().repaint();
v.getPanel().revalidate();
V is a class that extends JFrame and contains the panel in it AND
i is instance of SomeComponent