Writing into a buffered image
I made a simple paint program that allows the user draw on a panel. I want to be able to write whatever the user draws into a bufferedImage so that it can be displayed in another panel. How would I do that?
Thanks for your help.
Cheers,
Ryan
Painter Panel:
import java.util.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.colorchooser.*;
publicclass painterextends JPanelimplements ActionListener, ChangeListener{
private JPanel buttonPanel;
private JList sizeList;
private String drawSize="3";
privateint x, y;
private Color drawColor = Color.BLACK;
privateboolean firstRun =true;
private JColorChooser tcc;
// This array defines the pixel sizes that the paint brush can use.
privatefinal String pixSizes[] ={"1","2","3","4","5","6","7","8",
"9","10","12","15","20","30","40","50"};
// Setup the GUI.
public painter(){
// Listener to detect and log the drag of the mouse.
addMouseMotionListener(
new MouseMotionAdapter(){// anonymous inner class
publicvoid mouseDragged( MouseEvent event )
{
x = event.getX();
y = event.getY();
repaint();
}
}// end anonymous inner class
);// end call to addMouseMotionListener
// Establish the button panel.
buttonPanel =new JPanel();
buttonPanel.setLayout(new GridLayout(1,3) );
JButton colorButton=new JButton("Color");
colorButton.addActionListener(this);
//Set up color chooser for setting draw color
tcc =new JColorChooser();
tcc.getSelectionModel().addChangeListener(this);
tcc.setBorder(BorderFactory.createTitledBorder("Choose Draw Color"));
// This list allows the user to select the pixel size of the brush tool.
sizeList =new JList( pixSizes );
sizeList.setVisibleRowCount( 1 );
sizeList.setSelectionMode( ListSelectionModel.SINGLE_SELECTION );
sizeList.addListSelectionListener(
new ListSelectionListener(){
publicvoid valueChanged( ListSelectionEvent event )
{
drawSize = pixSizes[sizeList.getSelectedIndex()];
}
}
);
// Create the save button which will save whatever has been drawn
// so far and copy it into the display panel.
JButton saveButton =new JButton("Save" );
saveButton.addActionListener(
new ActionListener(){
publicvoid actionPerformed( ActionEvent event )
{
// Don't know what to do here.
}
}
);// End of actionListener definition.
buttonPanel.add( colorButton );
buttonPanel.add(new JScrollPane( sizeList ) );
buttonPanel.add( saveButton );
setLayout(new BorderLayout());
// Add the button panel to the bottom of the container.
add( buttonPanel, BorderLayout.SOUTH );
setSize( 300, 300 );
setVisible(true );
setBackground(Color.WHITE);
}// End of the constructor.
publicvoid paint( Graphics g )
{
// Set the size of the brush based on the selection from the sizeList.
int pixelSize = Integer.parseInt(drawSize);
// Only clear the paint area if this is the first repaint().
if ( firstRun ==true ){
super.paint( g );
firstRun =false;
}
// Set the color to whatever color is selected with the colors combo
// box.
g.setColor(drawColor);
// Draw the selected shape along all of the points dragged with the
// selected size.
g.fillOval( x, y, pixelSize, pixelSize );
}
publicvoid actionPerformed(ActionEvent e){
Color newColor = JColorChooser.showDialog(
painter.this,
"Choose Draw Color",
drawColor);
if (newColor !=null){
drawColor = newColor;
}
}
publicvoid stateChanged(ChangeEvent e){
drawColor = tcc.getColor();
}
}
[7948 byte] By [
trek1413a] at [2007-11-27 6:14:39]

# 1
If you want to draw the component graphics into a BufferedImage you can do something like this.
private void saveAsImage() {
int w = getWidth();
int h = getHeight() - buttonPanel.getHeight();
int type = BufferedImage.TYPE_INT_RGB;
BufferedImage toImage = new BufferedImage(w, h, type);
Graphics2D g2 = toImage.createGraphics();
paint(g2);
g2.dispose();
JOptionPane.showMessageDialog(this, new ImageIcon(toImage), "",
JOptionPane.PLAIN_MESSAGE);
}
For pen–style drawing it is easier to do all drawing on a BufferedImage. In this you
can use multiple colors and the drawings do not disappear with system repaints, eg, after
you minimize/restore the app. To clear/erase the image just set it to null and call
repaint.
import java.util.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.io.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.colorchooser.*;
public class PainterRx extends JPanel implements ActionListener, ChangeListener {
private JPanel buttonPanel;
private JList sizeList;
private String drawSize = "3";
private int x, y;
private Color drawColor = Color.BLACK;
private boolean firstRun = true;
private JColorChooser tcc;
BufferedImage image;
// This array defines the pixel sizes that the paint brush can use.
private final String pixSizes[] = {
"1", "2", "3", "4", "5", "6", "7", "8",
"9", "10", "12", "15", "20", "30", "40", "50"
};
// Setup the GUI.
public PainterRx() {
// Listener to detect and log the drag of the mouse.
addMouseMotionListener(
new MouseMotionAdapter() { // anonymous inner class
public void mouseDragged( MouseEvent event ) {
x = event.getX();
y = event.getY();
updateImage();
repaint();
}
} // end anonymous inner class
); // end call to addMouseMotionListener
// Establish the button panel.
buttonPanel = new JPanel();
buttonPanel.setLayout( new GridLayout(1,3) );
JButton colorButton= new JButton("Color");
colorButton.addActionListener(this);
//Set up color chooser for setting draw color
tcc = new JColorChooser();
tcc.getSelectionModel().addChangeListener(this);
tcc.setBorder(BorderFactory.createTitledBorder("Choose Draw Color"));
// This list allows the user to select the pixel size of the brush tool.
sizeList = new JList( pixSizes );
sizeList.setVisibleRowCount( 1 );
sizeList.setSelectionMode( ListSelectionModel.SINGLE_SELECTION );
sizeList.addListSelectionListener(
new ListSelectionListener() {
public void valueChanged( ListSelectionEvent event ) {
drawSize = pixSizes[sizeList.getSelectedIndex()];
}
}
);
// Create the save button which will save whatever has been drawn
// so far and copy it into the display panel.
JButton saveButton = new JButton( "Save" );
saveButton.addActionListener(
new ActionListener() {
public void actionPerformed( ActionEvent event ) {
save();
//saveAsImage();
}
}
); // End of actionListener definition.
buttonPanel.add( colorButton );
buttonPanel.add( new JScrollPane( sizeList ) );
buttonPanel.add( saveButton );
setLayout(new BorderLayout());
// Add the button panel to the bottom of the container.
add( buttonPanel, BorderLayout.SOUTH );
setSize( 300, 300 );
setVisible( true );
setBackground(Color.WHITE);
} // End of the constructor.
protected void paintComponent( Graphics g ) {
if(image == null) initImage();
g.drawImage(image, 0, 0, this);
}
private void initImage() {
int w = getWidth();
int h = getHeight();
int type = BufferedImage.TYPE_INT_RGB;
image = new BufferedImage(w, h, type);
Graphics2D g2 = image.createGraphics();
g2.setBackground(getBackground());
g2.clearRect(0,0,w,h);
g2.dispose();
}
private void updateImage() {
Graphics g = image.getGraphics();
// Set the size of the brush based on the selection from the sizeList.
int pixelSize = Integer.parseInt(drawSize);
// Set the color to whatever color is selected with the colors combo
// box.
g.setColor(drawColor);
// Draw the selected shape along all of the points dragged with the
// selected size.
g.fillOval( x, y, pixelSize, pixelSize );
g.dispose();
}
private void save() {
String ext = "jpg";
File file = new File("painterRx." + ext);
try {
ImageIO.write(image, ext, file);
} catch(IOException e) {
System.out.println("Write error: " + e.getMessage());
}
image = null;
repaint();
}
private void saveAsImage() {
int w = getWidth();
int h = getHeight() - buttonPanel.getHeight();
int type = BufferedImage.TYPE_INT_RGB;
BufferedImage toImage = new BufferedImage(w, h, type);
Graphics2D g2 = toImage.createGraphics();
paint(g2);
g2.dispose();
JOptionPane.showMessageDialog(this, new ImageIcon(toImage), "",
JOptionPane.PLAIN_MESSAGE);
}
public void actionPerformed(ActionEvent e) {
Color newColor = JColorChooser.showDialog(
PainterRx.this,
"Choose Draw Color",
drawColor);
if (newColor != null) {
drawColor = newColor;
}
}
public void stateChanged(ChangeEvent e) {
drawColor = tcc.getColor();
}
public static void main(String[] args) {
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.getContentPane().add(new PainterRx());
f.setSize(400,400);
f.setLocation(200,200);
f.setVisible(true);
}
}
# 2
That works fantastically. Thank you so much for the help.
# 3
Alright, the image save works fine. What I want to do now is put the buffered image into a JLabel and then add that JLabel to a scroll pane in my that i created in the constructor of my main panel. Though, when I try to do so I get a "non-static variable cannot be accessed from a static context" error. This is the code I was using to access it:
private void saveAsImage() {
int w = getWidth();
int h = getHeight() - buttonPanel.getHeight();
int type = BufferedImage.TYPE_INT_RGB;
BufferedImage toImage = new BufferedImage(w, h, type);
Graphics2D g2 = toImage.createGraphics();
paint(g2);
g2.dispose();
Cghmn.display.add(new JLabel(new ImageIcon(toImage)));
image = null;
repaint();
}
I don't understand why this is occurring though because that method is not labeled as static. Would it be inherently static for some reason?
Thanks.
Cheers,
Ryan
Code for the main panel which creates the scroll pane object:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.text.*;
public class Cghmn extends JFrame{
public JScrollPane display;
public static boolean checkIP(String IP){
// Verify a valid IP.
return true;
}
/**
* Create the GUI and show it. For thread safety,
* this method should be invoked from the
* event-dispatching thread.
*/
private Cghmn() {
//Create and set up the window.
JFrame frame = new JFrame("CompuGlobalHyperMegaNet");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception unused) {
System.err.println("**ERROR**: Cannot change look and feel.");
}
// Initialize the file menu.
JMenu fileMenu = new JMenu( "File" );
fileMenu.setMnemonic( 'F' );
// Setup the IP menu item
JMenuItem connectItem = new JMenuItem( "Connect To..." );
connectItem.setMnemonic( 'I' );
// Add the About... item to the file menu.
fileMenu.add( connectItem );
connectItem.addActionListener(
new ActionListener() { // anonymous inner class
// Handle the event of the user clicking on About....
public void actionPerformed( ActionEvent event )
{
// Pop-up an option pane with a brief message about the
// program.
String IP;
boolean check = false;
while (!check){
IP = JOptionPane.showInputDialog(null, "Connect to IP:");
check = checkIP(IP);
if (check == false){
JOptionPane.showMessageDialog(null, "Invalid IP. " +
"Please put into the form X.X.X.X");
}
}
}
} // end anonymous inner class
); // end call to addActionListener
// Setup the About... menu item
JMenuItem aboutItem = new JMenuItem( "About..." );
aboutItem.setMnemonic( 'A' );
// Add the About... item to the file menu.
fileMenu.add( aboutItem );
aboutItem.addActionListener(
new ActionListener() { // anonymous inner class
// Handle the event of the user clicking on About....
public void actionPerformed( ActionEvent event )
{
// Pop-up an option pane with a brief message about the
// program.
JOptionPane.showMessageDialog( null,
"This is a chat client that can send and \n" +
"receive both texts and user-drawn pics.", "About",
JOptionPane.PLAIN_MESSAGE );
}
} // end anonymous inner class
); // end call to addActionListener
// Setup the Exit menu item
JMenuItem exitItem = new JMenuItem( "Exit" );
exitItem.setMnemonic( 'x' );
fileMenu.add( exitItem );
exitItem.addActionListener(
new ActionListener() { // anonymous inner class
// Handle the events for the user clicking on exit.
public void actionPerformed( ActionEvent event )
{
// Exit the program.
System.exit( 0 );
}
} // end anonymous inner class
); // end call to addActionListener
// Create the menu bar object and set it as the menu bar for the frame.
JMenuBar bar = new JMenuBar();
setJMenuBar( bar );
// Add all of the menus and buttons to the menu bar.
bar.add( fileMenu );
setLayout(new GridLayout(1,2));
add(display);
add(new Painter());
setSize(600,300);
setVisible(true);
}
public static void main( String args[] )
{
Cghmn application = new Cghmn();
application.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
}
}
# 4
About non-static variable cannot be accessed from a static context:
In this line
Cghmn.display.add(new JLabel(new ImageIcon(toImage)));
the Cghmn.display is the static context. The compiler is saying that the variable display is not declared as static so you cannot use static notation to access it. Try
display.add(new JLabel(new ImageIcon(toImage))); instead.
Some prefer
this.display.add(new JLabel(new ImageIcon(toImage)));.
# 5
You where given the answer to this question yesterday in you other posting on this topic.Quit wasting peoples time and do some searching and reading on your own.