JaVa
   

Adding Components

To refresh your memory a little, a component is an object used to represent a displayable rectangular area in pixels on screen and can also be used to handle events, such as the mouse and keyboard. For example, our Frame is a component; a button or a text field is also a component. A component is defined by the class java.awt.Component to which all other components are derived. For example, the java.awt.Button class is derived from Component. Below a component is the java.awt.Container class. Basically, any class that extends this class can "contain" a list of other components, which themselves can be containers (for example, the java.awt.Panel class, which is a simple container for storing other components). The java.awt.Button class on the other hand directly extends java.awt.Component and not java.awt.Container because a button can be displayed and receive events, like being clicked by the mouse, but it cannot itself contain other components. The button is therefore said to be an atomic or indivisible component. We can overcome one problem we have at the moment with our current TemplateGraphicsapp automatically by using a component to represent the displayable screen area of our Frame. The component can be added to the frame where drawing can be performed onto that, instead of directly painting in the paint method. This means that we can perform our drawing relative to the component, which is added to the displayable area inside the frame where we will not need to handle the top-left border offset pixels when we are drawing (i.e., using the translate method we saw before). We can alter our TemplateGraphicsapp as follows so that it uses a JPanel component for drawing. A JPanel is a simple Swing container class that we will draw our graphics onto.

import javax.swing.*;
import java.awt.*;
public class TemplateGraphicsapp extends JFrame
{
 public TemplateGraphicsapp()
 {
 super("Template Graphics app");
 setDefaultCloseOperation(EXIT_ON_CLOSE);
 setResizable(false);
 getContentPane().setLayout(null);
 getContentPane().add(new DisplayArea(new Rectangle(0, 0,
 DISPLAY_WIDTH, DISPLAY_HEIGHT)));
 setVisible(true);
 resizeToInternalSize(DISPLAY_WIDTH, DISPLAY_HEIGHT);
 }
 public void resizeToInternalSize(int internalWidth, int
 internalHeight)
 {
 Insets insets = getInsets();
 final int newWidth = internalWidth + insets.left +
 insets.right;
 final int newHeight = internalHeight + insets.top +
 insets.bottom;
 Runnable resize = new Runnable()
 {
 public void run()
 {
 setSize(newWidth, newHeight);
 }
 };
 if(!SwingUtilities.isEventDispatchThread())
 {
 try
 {
 SwingUtilities.invokeAndWait(resize);
 }
 catch(Exception e) {}
 }
 else
 resize.run();
 validate();
 }
 public class DisplayArea extends JPanel
 {
 public DisplayArea(Rectangle bounds)
 {
 setLayout(null);
 setBounds(bounds);
 setOpaque(false);
 }
 public void paintComponent(Graphics g)
 {
 Graphics2D g2D = (Graphics2D)g;
 g2D.setColor(Color.blue);
 g2D.fill(getBounds());
 g2D.setColor(Color.white);
 g2D.fillRect(getWidth()/4, getHeight()/4, getWidth()/2,
 getHeight()/2);
 }
 }
 public static void main(String[] args)
 {
 new TemplateGraphicsapp();
 }
 private static final int DISPLAY_WIDTH = 400;
 private static final int DISPLAY_HEIGHT = 400;
}


The nested class DisplayArea extends JPanel where we provide our own overridden painting method paintComponent similar to overriding the paint method for the top-level frame and applet earlier. In the frames constructor, we add a new instance of our display area to the content pane of the frame. When this is done, we no longer need to worry about the border positions when drawing in the paintComponent method, as the component is added at the origin of the viewable display area of the frame. One thing to note about the JPanel is that it is opaque by default. This means that it will draw a background rectangle in its given bounds before invoking the paintComponent method. Because we are drawing the full displayable area, we do not need to do this so we call setOpaque(false); this is advantageous if you want to show parts drawn by the underlying parent component. Now that we are using components, the validate method is important for resizing the subcomponents of the window. Try leaving the call to validate out, and you'll see the non-resized internal DisplayArea component instead.

JaVa
   
Comments