Graphics
1. Understanding graphical coordinate systems
We have learned about GUI components offered by Swing and Layout managers. We know for example how to create a JButton and add it into a JFrame/JPanel and display/show the button on the frame/window. When you are doing this, you don’t need to care about how the Java will draw the components for you. However if you want to create a personalized component, for example, draw a cross on a button, what can you do? Java offers the capability of drawing text and geometrical graphics.
1.1 Coordinate systems
To draw such as a colored point or a line, you need to know where to draw. The location should be specified by coordinates of the point or line segment. Java’s coordinate system is different from the conventional coordinate system that you learnt in geometry. The y-axis of the Java coordinate system is up-side down as shown in the following figure. The unit is pixel.
Each component can be viewed as a canvas on which you draw/paint, so each component has its own coordinate system. All the drawing on the component will be located based on its own coordinate system.
A component C can be added into a container called its parent component, then C.getX() and C.getY() give the coordinate of the upper-left corner of C in its parent component’s system. Figure 13.4 gives a good description of the relation.
1.2 The Graphics class
All the drawing methods are defined in the Graphics class, a helper class defined in AWT. Each component has its own Graphicsinstance which can be obtained by calling component’s getGraphics method. To draw/paint on a component, you must use thisGraphics instance from the component. For example, to draw something to a button btn, you should get the Graphics instance first
Graphics mygraphics = btn.getGraphics();
There are a lot of built-in drawing methods in a Graphics instance. For example you can use drawLine method to draw a line on a button. See the following code
import javax.swing.*;
import java.awt.*;
import java.awt.*;
public class TestSimpleDrawing extends JFrame {
private JButton btn = new JButton("ITC 313");
public TestSimpleDrawing(){
setLayout(new FlowLayout(FlowLayout.LEFT, 5,5));
btn.setBackground(Color.RED);
btn.setForeground(Color.GREEN);
add(btn);
setTitle("How to Draw");
setSize(300, 200);
setLocationRelativeTo(null);
}
public static void main( String[] argv ) {
TestSimpleDrawing myframe = new TestSimpleDrawing();
myframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
myframe.setVisible(true);
Graphics graphics = myframe.btn.getGraphics();
graphics.drawLine(0,0, 20, 20);
//draw a line from (0,0) to (20, 20)
}
}
private JButton btn = new JButton("ITC 313");
public TestSimpleDrawing(){
setLayout(new FlowLayout(FlowLayout.LEFT, 5,5));
btn.setBackground(Color.RED);
btn.setForeground(Color.GREEN);
add(btn);
setTitle("How to Draw");
setSize(300, 200);
setLocationRelativeTo(null);
}
public static void main( String[] argv ) {
TestSimpleDrawing myframe = new TestSimpleDrawing();
myframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
myframe.setVisible(true);
Graphics graphics = myframe.btn.getGraphics();
graphics.drawLine(0,0, 20, 20);
//draw a line from (0,0) to (20, 20)
}
}
Try the above program and change (0, 0, 20, 20) to different values like (0, 0, 100, 200) to see what will happen.
1.3 Working with the paint component method
The last program shows you how to draw a line on a component. But there is a problem with it. For example, if you resize the window the line will disappear (actually the line does not appear sometimes when you run the program). See page 482 for the reasons.
In the JComponent class there is a method called paintComponent. The method will be automatically called every time when for example you resize the frame.
To make sure your drawing will be repainted on the component, you need to do two things:
- Extend a component where you want to draw something
- Re-define the paintComponent method with a Graphics parameter g and begin with the first statementsuper.paintComponent(g) in the method.
super.paintComponent(g) is important because it is responsible for re-drawing the contents in the supercomponent where you extend from.
Please read and try the example in Listing 13.1. In this example, you may note that you don’t need to create a Graphics instance. When the JLabel is going to be redrawn, the JLabel’s paintComponent method will be automatically invoked and the system provides theGraphics object g to the method.
2. Working with 2D shapes and text
Although you can draw on any components by using the Graphics instance from the component, most of time you draw shapes and text on a JPanel. Panels are invisible. In the preceding topic we use a panel to hold sub-components.
To draw in a JPanel, you extend JPanel and override the paintComponent method to tell the panel how to draw things. The basic template should look like
class myDrawingOnPanel extends JPanel {
protected void paintComponent(Graphics g) {
super.paintComponent(g); // this must be the first statement
//drawing any things you like with g
//read the following for how-to-draw
}
// other stuff for example you may define a constructor
}
protected void paintComponent(Graphics g) {
super.paintComponent(g); // this must be the first statement
//drawing any things you like with g
//read the following for how-to-draw
}
// other stuff for example you may define a constructor
}
2.1 Drawing strings
You should use the drawString method of the Graphics class to draw a string(text) on a panel. Put the following statement in the definition of paintComponent method,
g.drawString(“Text to be drawn”, x_coord, y_coord);
where (x_coord, y_coord) is the coordinate of the starting point of drawing in the JPanel’s coordinate system.
2.2 Drawing lines
A line segment can be determined by two ending points. To draw a line you need to provide the coordinates of the two points on the system. Then put the following statement in the paintComponent method
g.drawLine(x1, y1, x2, y2);
2.3 Drawing rectangles and ovals
A rectangle can be determined by the upper-left corner and its width and height. Thus you need provide the coordinate (x, y) of the upper-left corner and the width and height to the drawing method,
g.drawRect(x, y, width, height);
An oval can be drawn based on its bounding rectangle, so its drawing method is similar to drawRect method
g.drawOval(x, y, width, height);
2.4 Drawing polylines and polygons
For a series of points, you can connect them one with the next by lines, then you have a polyline. To draw it, you should provide the coordinates of all the points, but you must organize x-coordinates in one array and y-coordinates in another array, then take these with the number of points as the parameters to the drawing method,
g.drawPolyline(int[] x, int[] y, int nPoints);
for example
int x[] = {24, 45, 21, 35, 10};
int y[] = {15, 39, 22, 31, 9};
g.drawPolyline(x, y, x.length);
int y[] = {15, 39, 22, 31, 9};
g.drawPolyline(x, y, x.length);
Similarly you can draw a polygon by
g.drawPolygon(int[] x, int[] y, int nPoints);
which additionally connects the first point and the last point by a line. Try
int x[] = {24, 45, 21, 35, 10};
int y[] = {15, 39, 22, 31, 9};
g.drawPolygon(x, y, x.length);
int y[] = {15, 39, 22, 31, 9};
g.drawPolygon(x, y, x.length);
Note: if the first point and the last point are the same, the drawings drawn by the drawPolyline and drawPolygon look like each other. But they are not the same shapes. The polygon is a closed shape but polyline is not.
2.5 Filling your drawing
For closed geometrical shapes like retangles, ovals, and polygons, you can fill the inner areas with the paint color when you draw them, however you need use the corresponding filling methods like
g.fillRect(x, y, width, height);
g.fillOval(x, y, width, height);
g.fillPolygon(int[] x, int[] y, x.length);
g.fillOval(x, y, width, height);
g.fillPolygon(int[] x, int[] y, x.length);
2.6 Coloring your drawing
Before you draw your shapes, you can select a color for your drawing by using like
g.setColor(Color.RED);
before your drawing method.
2.7 Drawing (displaying) images
Please refer to Sections 13.10 and 13.11.
3. The Graphics 2D class
The Graphics class had methods to draw lines, rectangles, ovals and so on, but those drawing operations are very limited. For example, you cannot vary the line thickness and you cannot rotate the shapes.
The Graphics class was extended to the Graphics2D class which provides more sophisticated control over geometry, coordinate transformations, color management, and text layout. This is the fundamental class for rendering 2?dimensional (2D) shapes, text and images on the Java platform.
We are not going to discuss the Graphics2D class, but just give a general description about the usage. If you are interested in it, please refer to the Java document for more details regarding the usage.
First in the definition of the paintComponent method, you should cast the Graphics parameter into a Graphics2D
void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
// draw with g2;
….
}
Graphics2D g2 = (Graphics2D) g;
// draw with g2;
….
}
Second, the Java 2D library organizes geometric shapes in an object-oriented fashion. To draw a shape, for example, a rectangle, you should create an object of the Rectangle2D class and call the draw method in the following way
Rectangle2D a_rect = …. //creat an object;
g2.draw(a_rect);
g2.draw(a_rect);
If you want to fill a closed shape, use the fill method.
No comments:
Post a Comment