Graphics
Graphics is the field in Computer Science that covers the display of pictures on the screen. As with GUIs, a lot of very smart people spend extensive research time, energy, and money doing this well (for example, on accurate-looking modelling of cloth motion). We only have one day to spend on this topic... so we're going to draw simple shapes, and learn how Java lets us have them show up on the screen.
Essentially, the idea is this: JComponents are displayed in a way determined by a method called paint(). So, we create our OWN JComponents, and override the paint() method. Let's look at an example.
import javax.swing.*;
import java.awt.*;
public class SimpleGraphics {
private static class BeatArmy extends JComponent {
public void paint(Graphics g) {
g.setFont(new Font("Segoe UI", Font.BOLD,50));
g.drawString("Go Navy! Beat Army!", 100,100);
}
}
public static void main(String[] args) {
JFrame frame = new JFrame("A Frame!");
BeatArmy ba = new BeatArmy();
frame.add(ba);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(800,200);
frame.setVisible(true);
}
}
In this case, we created a class called BeatArmy, which extends JComponent. We then overloaded the paint method, calling setFont and drawString methods. As with GUIs, we haven't the time or inclination to learn about all of these methods that Graphics can do; I do, however, want you to remember that you make custom graphics by making your own JComponents, and overriding paint().
Let's look at another example.
import javax.swing.*;
import java.awt.*;
public class SimpleBall {
public static class BallPanel extends JComponent {
private int x, y, d;
public BallPanel(int x, int y, int d) {
super();
this.x = x;
this.y = y;
this.d = d;
}
public void paint(Graphics g) {
g.fillOval(x,y,d,d);
g.setColor(Color.black);
}
}
public static void main(String[] args) {
JFrame frame = new JFrame("Ball");
BallPanel bp = new BallPanel(100,100,20);
frame.add(bp);
frame.setSize(500,500);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
This is a slightly more complicated example. Here, our BallPanel has a constructor that takes x and y coordinates, and a diameter. Our paint method then calls fillOval and setColor to draw a ball of that size, in that place.
Images
It is pretty easy to display an image in this, as well, using a BufferedReader:
import javax.swing.*;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
public class MakeImage {
public static class ImgPanel extends JComponent {
private BufferedImage img;
public ImgPanel(String fn) {
try{
img = ImageIO.read(new File(fn));
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
public void paint(Graphics g) {
g.drawImage(img, 5, 5, null);
}
}
public static void main(String[] args) {
JFrame frame = new JFrame("Diana");
ImgPanel ip = new ImgPanel("diana_bssrdf.jpg");
frame.add(ip);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(760,760);
frame.setVisible(true);
}
}
Animation
We can take these concepts, and create animation! If we have a JComponent jc, and call jc.repaint(), then the paint() method gets called again. Consider the following example.
import javax.swing.*;
import java.awt.*;
public class Ball {
public static class BallPanel extends JComponent {
private int x, y, d;
private double xv, yv;
public BallPanel(int x, int y, int d) {
super();
this.x = x;
this.y = y;
this.d = d;
xv = 3;
yv = 5;
}
public void paint(Graphics g) {
Dimension size = getSize(); //returns the size of the BallPanel
g.fillOval(x,y,d,d);
g.setColor(Color.black);
if ((x+(d/2)>=size.width && xv>0)
|| (x-(d/2)<=0 && xv < 0))
xv *= -1;
if ((y+(d/2)>=size.height && yv > 0)
|| (y-(d/2)<=0 && yv < 0))
yv *= -1;
x += xv;
y += yv;
}
}
public static void main(String[] args) {
JFrame frame = new JFrame("Ball");
BallPanel bp = new BallPanel(100,100,20);
frame.add(bp);
frame.setSize(500,500);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
while (true) {
try{
Thread.sleep(33);
} catch (InterruptedException ie) {
ie.printStackTrace();
}
bp.repaint();
}
}
}
In this example's BallPanel, every time we call bp.repaint() in the loop in main(), we run the code inside paint() again, resulting in the changing of x and y, for the next run. As a result, the ball bounces around the screen!
What about MouseListeners? (Yes, we're showing off at this point.) Download and run Ripple.java. Try clicking around on it. What happens? Why?