问题
I'm newbie in jave, my first project is draw, and save a image from JPanel, my draw is done, but I cant save it after I draw in JPanel :(, So can you help me to fix it when I open the image after draw, It doesn't contain anything :( here my codes:
package image;
import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Graphics;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
public class paint extends JFrame{
private Point points[] = new Point[10000];
private Point pointends[] = new Point[10000];
private int pointCount = 0;
private JButton save_btn;
public paint()
{
panel paint2 = new panel();
add(paint2,BorderLayout.CENTER);
}
private class panel extends JPanel
{
private paint my_paint;
public panel()
{
setBackground(Color.WHITE);
save_btn = new JButton();
save_btn.setText("123");
this.add(save_btn);
ButtonHandler handler1 = new ButtonHandler();
save_btn.addActionListener(handler1);
MouseHandler handler = new MouseHandler();
this.addMouseMotionListener(handler);
this.addMouseListener(handler);
}
private class ButtonHandler implements ActionListener
{
@Override
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
savefile();
}
}
@Override
protected void paintComponent(Graphics g)
{
// TODO Auto-generated method stub
super.paintComponent(g);
for(int i = 0;i <pointCount;i++)
{
g.setColor(Color.RED);
g.drawLine(points[i].x, points[i].y, pointends[i].x, pointends[i].y);
}
}
private class MouseHandler extends MouseAdapter
{
@Override
public void mouseDragged(MouseEvent e)
{
// TODO Auto-generated method stub
pointends[ pointCount-1] = e.getPoint();
repaint();
}
@Override
public void mousePressed(MouseEvent e) {
// TODO Auto-generated method stub
super.mousePressed(e);
if(pointCount < points.length)
{
points[ pointCount ] = e.getPoint();
pointends[ pointCount ] = e.getPoint();
pointCount++;
repaint();
}
}
@Override
public void mouseReleased(MouseEvent e) {
// TODO Auto-generated method stub
super.mouseReleased(e);
/*pointends[pointCount]=e.getPoint();
repaint();
pointCount++;
*/
}
}
}
public void savefile()
{
BufferedImage image2 = new BufferedImage(panel.WIDTH, panel.HEIGHT, BufferedImage.TYPE_INT_RGB);
JFileChooser jFile = new JFileChooser();
jFile.showSaveDialog(null);
Path pth = jFile.getSelectedFile().toPath();
JOptionPane.showMessageDialog(null, pth.toString());
Graphics2D graphics2D = image2.createGraphics();
try {
ImageIO.write(image2, "", new File(pth.toString()));
} catch (IOException ox) {
// TODO: handle exception
ox.printStackTrace();
}
}
}
回答1:
private void saveImage(){
BufferedImage imagebuf=null;
try {
imagebuf = new Robot().createScreenCapture(panel.bounds());
} catch (AWTException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
Graphics2D graphics2D = imagebuf.createGraphics();
panel.paint(graphics2D);
try {
ImageIO.write(imagebuf,"jpeg", new File("save1.jpeg"));
} catch (Exception e) {
// TODO Auto-generated catch block
System.out.println("error");
}
}
回答2:
Create BufferedImage to store your painting. When you paint, paint on BufferedImage.
When you need to display paint on JPanel, draw BufferedImage on JPanel.
This way, you can load / save painting to file.
Something like this:
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 Paint extends JPanel{
private BufferedImage paintImage = new BufferedImage(500, 400, BufferedImage.TYPE_3BYTE_BGR);
@Override
protected void paintComponent(Graphics g){
super.paintComponent(g);
g.drawImage(paintImage, 0, 0, null);
}
// draw painting
public void updatePaint(){
Graphics g = paintImage.createGraphics();
// draw on paintImage using Graphics
g.dispose();
// repaint panel with new modified paint
repaint();
}
public void save() throws IOException{
ImageIO.write(paintImage, "PNG", new File("filename.png"));
}
public void load() throws IOException {
paintImage = ImageIO.read(new File("filename.png"));
// update panel with new paint image
repaint();
}
}
回答3:
There is a nice approach:
BufferedImage image = new BufferedImage(component.getWidth(), component.getHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics g = image.getGraphics();
component.paint(g);
try {
ImageIO.write(image, "png", new File(filename));
} catch (IOException ex) {
Logger.getLogger(CustomApp.class.getName()).log(Level.SEVERE, null, ex);
}
All what it does: It creates an image with visible component's size and ARGB type for transparency support. Then it get the graphics and pass that to the component we want to have snapshot of. It paints that component's child component including anything drawn on it.
Update: You can use component.print(Graphics g) too:
Dimension componentSize = component.getPreferredSize();
component.setSize(componentSize); // need to make sure that both sizes are equal
BufferedImage image = new BufferedImage(comonent.getWidth(), component.getHeight(), BufferedImage.TYPE_INT_RGB);
Graphics g = image.createGraphics();
g.fillRect(0, 0, image.getWidth(), image.getHeight());
component.print(g);
But this function will draw only the rendered graphics of the component but not the child components. I have tested it.
Edit:
- Your
paint extends JFrameclass can have a nice name, e.g.,PaintFrame extends JFrame. Class name should not have a name of a function, paint is averb, it is a function. panel extends JPanel: why should we go down choosing a class name with first letter of lower case? We can give our component name to reflect what we are doing with it: like, we are drawing so what aboutMyCanvas extends JPanel- Inside the
panelyour first statementprivate paint my_paint;: what is it doing here unnecessarily ? - your
saveFile()function belongs to theJFrameand you have created yourpanel(on which you are drawing) local to the frame constructor. How should thesaveFile()function have access to it? Declare your painting Panel in the JFrame class context aspublicorprivate. I have written in a meaningful way to read the sizes of the component using
getWidth()andgetHeight()But you are writing:BufferedImage image2 = new BufferedImage(panel.WIDTH, panel.HEIGHT, ...);
And again i have completely written the code how to save the image as a png using ImageIO.write(image, "png", "myFile.png") function. Please read the answers carefully.
Following resources might be helpful:
- A closer look at painting mechanism.
- Writing and saving images
回答4:
Screen Image allows you to save an image of any component.
来源:https://stackoverflow.com/questions/19621105/save-image-from-jpanel-after-draw