Drawing an arc in Swing

Use the method drawArc that accepts the left and right coordinate, the height and width of the circle, the angle of the starting point and the angle of the arc. In this example, an arc is drawn from 90 degrees for 45 degrees.

Main.java:

import java.awt.event.*;
import javax.swing.*;
import java.awt.*;
 
public class Main extends JFrame {
   public Main() {
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent we) {
            System.exit(1);
         }
      });
   }
 
   public void paint(Graphics g) {
      Graphics2D g2d = (Graphics2D) g;
  
      g2d.drawArc(10, 50, getSize().width-20, getSize().height-50, 90, 45);
   }
 
   public static void main(String []args) {
      Main main = new Main();
      main.setSize(100, 100);
      main.setVisible(true);
   }
}

Drawing a line in Swing

Use the method drawLine that accepts the line end coordinates (x1, y1) and (x2, y2).

Main.java:

import java.awt.event.*;
import javax.swing.*;
import java.awt.*;
 
public class Main extends JFrame {
   public Main() {
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent we) {
            System.exit(1);
         }
      });
   }
 
   public void paint(Graphics g) {
      Graphics2D g2d = (Graphics2D) g;
  
      g2d.drawLine(10, 50, getSize().width-20, 15);
   }
 
   public static void main(String []args) {
      Main main = new Main();
      main.setSize(100, 100);
      main.setVisible(true);
   }
}

Switching to another display mode

From JDK1.4, you can use the class DisplayMode. Either instantiate a DisplayMode object by specifying width, height, bitdepth and refreshrate, or get a list of available DisplayModes by calling the method getDisplayModes on the current GraphicsDevice.

When you’ve made up your mind about the display mode, call the method setFullScreenWindow to get the device into “full-screen exclusive mode” (necessary) and the method setDisplayMode to perform the display change.

Main.java:

import javax.swing.*;
import java.awt.event.*;
import java.util.*;
import java.awt.*;
 
public class Main extends JFrame {
   DisplayMode oldDm;
 
   public Main() {
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent we) {
            System.exit(1);
         }
      });
 
      GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment (); 
      final GraphicsDevice gd = ge.getDefaultScreenDevice ();
 
      oldDm = gd.getDisplayMode();
      final DisplayMode dm[] = gd.getDisplayModes();
 
      Vector v = getDisplayModesAsStrings(dm);
      final JComboBox cb = new JComboBox(v);
      cb.addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent ae) {
            int selectedIndex = cb.getSelectedIndex();
            gd.setFullScreenWindow(Main.this);
        
            if (gd.isDisplayChangeSupported()) {
               try {
                  gd.setDisplayMode(dm[selectedIndex]); 
               } catch(Exception e) {
                  gd.setDisplayMode(oldDm);
               }
            }
            else {
               System.out.println("Display change not supported!");
            }            
         }
      });
 
      getContentPane().setLayout(new FlowLayout(FlowLayout.LEFT, 10, 10));
      getContentPane().add(new JLabel("Change to display mode:"));
      getContentPane().add(cb);
      pack();  
   }
 
   public Vector getDisplayModesAsStrings(DisplayMode dm[]) {
      Vector v = new Vector();
 
      for (int i=0; i<dm.length; i++) {
         int width = dm[i].getWidth();
         int height = dm[i].getHeight();
         int bitDepth = dm[i].getBitDepth();
         int refreshRate = dm[i].getRefreshRate();
         v.add("" + width + "x" + height + " " + bitDepth + "bit " + 
                              (refreshRate == 0 ? "unknown" : ""+refreshRate + "hz"));
      }
 
      return v;
   }
 
   public static void main(String[] args) {
      Main main = new Main();
      main.setVisible(true);
   } 
}

Getting a list of all display modes

From JDK1.4, you can use the class DisplayMode. Get the current GraphicsDevice, and call the method getDisplayModes.

Main.java:

import javax.swing.*;
import java.awt.*;
 
public class Main extends JFrame {
   public static void main(String[] args) {
      GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment ();
 
      GraphicsDevice gd = ge.getDefaultScreenDevice ();
 
      DisplayMode dp[] = gd.getDisplayModes();
 
      for (int i=0; i<dp.length; i++) {
         int width = dp[i].getWidth();
         int height = dp[i].getHeight();
         int bitDepth = dp[i].getBitDepth();
         int refreshRate = dp[i].getRefreshRate();
         System.out.println(width + "x" + height + " " + 
                            bitDepth + "bit " + 
                            (refreshRate == 0 ? "unknown" : ""+refreshRate + "hz"));
      }
   } 
}

outputs on my machine:

640x480 8bit unknown
800x600 8bit unknown
1024x768 8bit unknown
1152x864 8bit unknown
1280x1024 8bit unknown
640x480 16bit unknown
800x600 16bit unknown
1024x768 16bit unknown
1152x864 16bit unknown
1280x1024 16bit unknown
640x480 32bit unknown
800x600 32bit unknown
1024x768 32bit unknown
1152x864 32bit unknown
1280x1024 32bit unknown

Converting an int array into an image

How can a int array be converted into an Image?
Well, that depends on the format in which the image is stored inside the int array. I will assume that each pixel is stored into a single int in aRGB format (1st byte – alpha, 2nd byte – red, 3rd byte – green, 4th byte – blue), and that the array contains the pixel values row by row (meaning that first the array contains the upper most row of the image, then the 2nd row, then the 3rd etc.) If you have it stored in a different format, convert to this one first.
Here’s code that does the trick:

/**
 * Creates an Image object from the given array of pixels.
 *
 * @param pixels The pixels array.
 * @param width The width of the Image.
 * @param height The height of the Image.
 *
 * @return An Image object representing the image stored
 * in the given int array.
 */

public static Image createImage(int [] pixels, int width, int height){
  MemoryImageSource imageSource = new MemoryImageSource(width,height,pixels,
                                                        0,width);
  return Toolkit.getDefaultToolkit().createImage(imageSource);
}

How can an image be displayed as fast as possible
Well, obviously we are drawing images using one of the various Graphics.drawImage() methods, so apparently there’s nothing we can do to speed up the drawing… The tricky part here is to know that images created with an ImageProducer such as ones we’ve created in the first question (and ones you usually create with the getImage() methods) draw much slower than images created with the Component.createImage(width,height) method. So how do we obtain such a fast drawing image? Simple – let’s draw the slow drawing image on the fast drawing image once and then draw the fast drawing image on the screen every time.
Here’s code that does this:


/**
 * Creates a new offscreen Image that will contain the same
 * data as the given image. The given Image must be preloaded.
 *
 * @param img The source image.
 * @param component Any onscreen component (one that has a peer).
 *
 * @return An offscreen copy of the given image.
 */
 
public static Image toOffscreenImage(Image img, Component comp){
  int width = img.getWidth(null);
  int height = img.getHeight(null);
  Image offScreenImage = comp.createImage(width,height);
  offScreenImage.getGraphics().drawImage(img,0,0,null);
  return offScreenImage;
}

It is important that the Component you give to the above method is onscreen (has a peer), meaning it’s inside a toplevel container (Window, Frame, Dialog) whose setVisible(true) method has been called.

Transferring an Image over the network

Serialization won’t work here because the actual contents of the image (the colors of the pixels) is kept in native code and Serialization only works on Java objects.

The solution is to obtain pixel values and write them into a socket. On the other side, the pixel values must be read and converted into an Image again. Here’s a method that takes an Image and writes its pixel color values into the given OutputStream:

/**
 * Grabs the pixels of the given Image object and returns the array of those
 * pixels. Note that the Image needs to be preloaded in order for this
 * method to work correctly.
 * 
 * @param Image img: The image whose pixels to grab.
 * 
 * @return The values of the pixels encoded in 4 bytes each
 * in aRGB format.
 */

public static int [] grabPixels(Image img){
  int width = img.getWidth(null);
  int height = img.getHeight(null);
  int [] pixels = new int[width*height];
  PixelGrabber grabber = new PixelGrabber(img,0,0,width,height,pixels,0,width);
  try{
    if (!grabber.grabPixels())
      return null;
  } catch (InterruptedException e){
      return null;
    }
  return pixels;
}
 
public static void writeImage(Image img, OutputStream out) throws IOException{
  int [] pixelValues = grabPixels(img);
  ObjectOutputStream objectOut = new ObjectOutputStream(out);  
  objectOut.writeObject(pixelValues); // Arrays are Serializable
}

And here is code that reads the pixel values from the given InputStream, creates and returns an Image object representing the image:

/**
 * Creates an Image object from the given array of pixels.
 * Note that the returned Image is created using an ImageProducer
 * (MemoryImageSource), and such Images are painted much slower than
 * offscreen Images created via Component.createImage(int,int) and you can't
 * draw on these Images as their getGraphics() method will return null. If
 * you need an Image that will be drawn fast and/or you need to paint
 * additional things on the Image, create an offscreen Image using
 * Component.createImage(int,int) and paint the Image returned by this method
 * on that Image.
 * Parameters:
 *   int [] pixels: The pixels array.
 *   int width: The width of the Image.
 *   int height: The height of the Image.
 */
 
public static Image createImage(int [] pixels, int width, int height){
  MemoryImageSource imageSource = new MemoryImageSource(width,height,pixels,
                                                        0,width);
  return Toolkit.getDefaultToolkit().createImage(imageSource);
}
 
 
public static Image readImage(InputStream in) throws IOException{
  ObjectInputStream objectIn = new ObjectInputStream(in);
  try{
    int [] pixelValues = (int [])objectIn.readObject();
  } catch (ClassNotFoundException e){} // This can't happen
    // since the class for (int []) must be present on every JVM
}

Creating a full screen AWT Frame

From 1.4 onwards, call the method setFullScreenMode on the default screen device.

Main.java:

import java.awt.event.*;
import java.awt.*;
 
public class Main extends Frame implements ActionListener
{
   public Main()
   {
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent we) {
            System.exit(1);
         }
      });
 
      Button maxButton = new Button("Make this Frame full-screen");
      setLayout(new FlowLayout(FlowLayout.LEFT));
      add(maxButton);
      maxButton.addActionListener(this);
   }
 
   public void actionPerformed(ActionEvent ae) {     
      GraphicsDevice device = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
      device.setFullScreenWindow(this);
   }
 
   public static void main(String args[])
   {
      Main main = new Main();
      main.setSize(300, 150);
      main.setVisible(true);
   }
}

Creating a Menu for a Frame

Main.java:

import java.awt.*;
import java.awt.event.*;

class MenuTest extends Frame implements ActionListener
{
   MenuBar menu=new MenuBar();
   Menu menuFile=new Menu("File");
   MenuItem menuFileQuit=new MenuItem("Quit");
 
   public static void main(String args[]) {
      MenuTest window=new MenuTest();
      window.show();
   }
 
   public MenuTest() {
      setMenuBar(menu);
      menu.add(menuFile);
      menuFile.add(menuFileQuit);
      menuFileQuit.addActionListener(this);
   }
  
   public void actionPerformed(ActionEvent e)
   {
      if (e.getSource()==menuFileQuit)
      {
         System.exit(0);
      }
   }
}

Maximizing an AWT Frame

From 1.3 onwards, use setExtendedState(Frame.MAXIMIZED_BOTH)

Main.java:

import java.awt.event.*;
import java.awt.*;
 
public class Main extends Frame implements ActionListener
{
   public Main()
   {
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent we) {
            System.exit(1);
         }
      });
 
      Button maxButton = new Button("Maximize this Frame");
      setLayout(new FlowLayout(FlowLayout.LEFT));
      add(maxButton);
      maxButton.addActionListener(this);
   }
 
   public void actionPerformed(ActionEvent ae) {     
      setExtendedState(Frame.MAXIMIZED_BOTH);
   }
 
   public static void main(String args[])
   {
      Main main = new Main();
      main.setSize(300, 150);
      main.setVisible(true);
   }
}

Iconifying a AWT Frame

Use setState(Frame.ICONIFIED) and setState(Frame.NORMAL).

Main.java:

import java.awt.event.*;
import java.awt.*;
 
public class Main extends Frame implements ActionListener
{
   public Main()
   {
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent we) {
            System.exit(1);
         }
      });
 
      Button iconButton = new Button("Iconify this Frame");
      setLayout(new FlowLayout(FlowLayout.LEFT));
      add(iconButton);
      iconButton.addActionListener(this);
   }
 
   public void actionPerformed(ActionEvent ae) {     
      this.setState(Frame.ICONIFIED);  
   }
 
   public static void main(String args[])
   {
      Main main = new Main();
      main.setSize(300, 150);
      main.setVisible(true);
   }
}