Description of the Simple Line Drawing program
JPT Techniques
Creating and using the ColorView
Creating and using the TextAreaView
Creating and using the BufferedPanel with graphics
Installing GUI Components Part 2
In this program we introduce the BufferedPanel, the ColorView and the TextAreaView.
The BufferedPanel is used to display graphics. The ColorView allows the user to select the color of the line before it is drawn. The TextAreaView is used to display the history: the coordinates of the lines already drawn.
We build a simple program that will let the user make a simple line drawing (possibly dot-to-dot) and select the color of the lines. Two snapshots of the view of the entire GUI are shown below.
The two snapshots illustrate the fact that the history panel automatically adds scrollbars, once it runs out of space to hold all information needed. In the first snapshot the line endpoints were chosen at random by the program. In the second snapshot the user selected the endpoints and also selected new color for some of the lines.
View
This program uses two pairs of TextFieldViews to allow the user to select two sets of endpoints for a line. The ColorView allows the user to select color of the line before it is drawn. The TextAreaView is used to display the history: the coordinates of the lines already drawn. The graphics is displayed in a BufferedPanel.
Model
The internal data model consists of two Point2D.Double objects that represent the two endpoints of the line. These two objects are instantiated every time the draw action is selected. The line is drawn, the history is recorded, the TextFieldViews are set to new values, and the objects die as the action method exits. This represents the Model part of the program.
Actions
The program uses one ActionsPanel with two associated Actions. The clear Action clears the history, the graphics window, and resets the four TextFieldViews to the original default values used in the constructor. The draw Action extracts the coordinates for the endpoints of a line from the TextFieldViews, extracts the color from the ColorView, sets the color, draws the lines, and performs several view update operations. It records the current line in the history, makes the current endpoint a suggested start point for the next line, and selects a random point to be the suggested next endpoint. This represents the Action part of the program.
GUI
The GUI is enclosed in a QuickJPTFrame titled Simple Line Drawing. The SimpleDrawing class extends the DisplayPanel class and uses a BorderLayout to organize its appearance. Each pair of TextFieldViews that represent the endpoints of a line is installed in a titled DisplayCollection. Together, these two displays are installed in a DisplayCollection with horizontal alignment. The TextAreaView that holds the history is installed in a ScrollableDisplay to make sure we can see all of the line coordinates as needed. The ColorView, the actions panel, and the TextAreaView, are combined in a DisplayCollection controls. The BufferedPanel is installed in a Display titled Graphics. Finally, the DisplayCollection controls, the DisplayCollection that holds the TextFieldViews. and the Graphics Display are installed in the proper locations in the SimpleDrawing DisplayPanel.
The diagram shows how the components fit together - omitting the lowest level text field views:
Creating and using the ColorView
The ColorView is used to display a selected color and allows the user to select a color for the graphics either through the use of the JColorChooser dialog, or by typing in the RGB values in the associated text field view. It is a JPT component that implements the Displayable interface. The programmer may choose to create a simple color view that contains only a color swatch or to instantiate the full color view that includes a color swatch and a corresponding text field view. The color text field view displays the RGB values for the currently selected color formatted as comma-separated integers. The user may change the selected color by typing the changes into the text field and hitting the RETURN key. Full scale parsing and the corresponding error strategy for the text field view will be activated. The suggestion for the error strategy will be set to the initial default color selected by the user in the constructor. The programmer may also select the number of clicks needed by the user to activate the JColorChooser dialog.
Additionally, the color text field view allows for specifying the color in the RGB-Alpha format, where the fourth integer defines the saturation level for the color. An example of its use can be found in the Circle Deluxe sample program and tutorial.
The ColorView is defined in the following statement:
// color view where user can select the color for the drawing
private ColorView color =
new ColorView(Color.red, true); // initial color is red
// include color text field view
In the constructor for the GUI we select the click count that activates the color chooser:
// activate color chooser using single click
color.setChooserClickCount(1);
Also in the constructor, we add the color view to the GUI, installing it as a wrapped titled display into the controls display collection:
// add color view to controls
controls.add(
new DisplayWrapper(
new Display(color, null, "Color")));
The current color selection can be extracted from the color view in several ways. The getColor and setColor methods use the Java Color class. The demandObject and requestObject methods call the getColor method and return an XColor object. The getViewState method first calls demandObject and then it converts the XColor it extracted to a String using the toStringData method in the XColor class. We extract the color from the color view inside the draw action in the following manner:
// set paint color to user color choice
G.setPaint(color.getColor());
where G is the graphics context for the BufferedPanel.
We also display the view state of the color view in the history panel as a comma-separated string using the getViewState method as follows:
// show the color and the line coordinates for history
history.append("(" + color.getViewState() + ")\n");
...
Creating and using the TextAreaView
A TextAreaView is a JPT component that implements the Displayable interface and can display several lines of text. If it is installed in a ScrollableDisplay, the scroll bars will automatically appear when needed. The entire contents of the TextAreaView can be extracted with a single getViewState method call that returns an XString object. The TextAreaView extends the Java Swing JTextArea class and so we can call the append method of JTextArea to add text to the TextAreaView.
We defined a TextAreaView object as follows:
// panel to display past graphed points
private TextAreaView history = new TextAreaView();
We set its size using the following two methods in the JTextArea class:
// set preferred size for the history text area
history.setColumns(13);
history.setRows(18);
The TextAreaView is installed in a ScrollableDisplay as follows:
// install history panel in a scrollable display
// add to controls wrapped with a title
controls.add(new DisplayWrapper(new Display(
new ScrollableDisplay(history), // installed as scrollable
null, // no annotation
"Lines drawn"))); // title for the display
Finally, we add text to the TextAreaView as follows:
// show the color and the line coordinates for history
history.append("(" + color.getViewState() + ")\n");
history.append("(" + (int)P1.x + ", " + (int)P1.y + ") : ");
history.append("(" + (int)P2.x + ", " + (int)P2.y + ")\n");
Creating and using the BufferedPanel with graphics
The JPT component used for the display of graphics is a BufferedPanel. The latest graphics content is stored in a buffer and repainted when desired or when Java deems it necessary. As a result, displaying graphics is very pleasing with no flickering. The BufferedPanel comes with an automatically installed mouse listener. This feature will be explored in a subsequent tutorial. Here we only show how it can be used to display simple output graphics. The standard Java Graphics2D package is used for creating the actual graphics content.
We declare the BufferedPanel and a graphics context object that will refer to this panel later as follows:
// square window for painting
private BufferedPanel window =
new BufferedPanel(bufferWidth, bufferHeight);
// graphics context to draw lines and other shapes
private Graphics2D G = null;
We add the BufferedPanel to the GUI in the constructor as follows:
// wrap the graphics window into a titled display
Display windowDisplay =
new Display(window, null, "Graphics");
Finally, in the actions methods, we retrieve the graphics context, install the new graphics objects, and call the repaint() method to show the updated graphics state:
// get the graphics context to draw the line
Graphics2D G = window.getBufferGraphics();
// set paint color to user color choice
G.setPaint(color.getColor());
// line to draw - from P1 to P2
Line2D.Double L = new Line2D.Double(P1, P2);
G.draw(L);
repaint();
Installing the GUI components – Part 2
There are three new ideas in this program. The simplest is the fact that the DisplayCollection has selected a horizontal orientation as follows:
// control panel to combine point data displays
private DisplayCollection pointData =
new DisplayCollection(HORIZONTAL);
Next, the main GUI component is now a DisplayPanel with a BorderLayout. That allows us to install the controls on the WEST, the pointData panel on the SOUTH and the graphics window in the CENTER:
// class declaration:
public class SimpleDrawing extends DisplayPanel
// beginning of the constructor:
public SimpleDrawing() {
// layout for panel as a whole
setLayout(new BorderLayout());
// adding the highest level components to the main panel:
add(controls, BorderLayout.WEST);
add(windowDisplay, BorderLayout.CENTER);
add(pointData, BorderLayout.SOUTH);
Finally, we show how the reset() function for the main panel recursively calls the reset functions for all components it contains:
public void clear() {
// reset all components
reset();
// Note: the reset() is called recursively for all components
// That means that the following statements will be invoked:
// controls.reset(); which will then call
// color.reset();
// history.reset();
// actions.reset();
//
// pointData.reset(); which will then call
// startPoint.reset();
// endPoint.reset();
//
// to reset all states to their initial defaults
// clear the graphics window
window.clearPanel();
repaint();
}
ColorView
ColorView constructor:
private ColorView color =
new ColorView (
Color.red, // initial color displayed in the color view
true); // true = use text field view
color the color view identifier
Color.red Color - initial
value that will be displayed in the color view and will be used as the default
and the suggestion value
true boolean - use the text
field view in addition to the color swatch
Selecting click count for activating the color chooser:
color.setChooserClickCount(1);
color the color view identifier
1 integer - the
number of clicks needed to activate the color chooser
Extracting Color from the color view:
Color col = color.getColor();
col identifier for the Color object that will get the color
color the color view identifier
Extracting color from the color view in the form of XColor object:
XColor xcol = color.demandObject(); // or
XColor xcol = color.requestObject();
xcol identifier for the XColor object that will get the color
color the color view identifier
Note: only the mandatory model is supported for color view
Note: suggestion is automatically set to the initial color value
Extracting color from the color view in the form of a formatted String:
String colorString = color.getViewState();
colorString identifier for the String object that will get the formatted string representing the color
color the color view identifier
Setting the color form a formatted String in the data model:
color.setViewState(r + "," + g + "," + b);
color the color view identifier
r int - the red shade value
g int - the green shade value
b int - the blue shade value
Adding a color view to a Display:
controls.add(new Display(color, null, "Color:")));
controls identifier of a DisplayPanel
or a DisplayCollection
to which the color view is added
color identifier for the color view that is being installed
Sum String - the title that will appear on the top of the display border
null String - the annotation that will appear to the left of the view
Alternative way for adding a the color view to a Display:
controls.add(
new DisplayWrapper(
new Display(color, null, "Color:")));
By using the DisplayWrapper we assure that the color view will retain a sensible size when the window where it is contained is changes its size.
TextAreaView
TextAreaView constructor:
private TextAreaView history =
new TextAreaView();
history identifier for the TextAreaView object
Install TextAreaView into a scrollable display:
controls.add(
new DisplayWrapper(
new Display(new ScrollableDisplay(history), null, "History"));
controls identifier for the Display object where we install the scrollable
history identifier for the TextAreaView object
"History" title for the scrollable display
Append text to the TextAreaView:
history.append("Text to be appended");
history identifier for the TextAreaView object
"Text..." String that will be appended to the TextAreaView
BufferedPanel
BufferedPanel constructor:
private BufferedPanel window =
new BufferedPanel(bufferWidth, bufferHeight);
window identifier for the BufferedPanel object
bufferWidth integer constant indicating the width in pixels
bufferHeight integer constant indicating the height in pixels
Adding the BufferedPanel panel to the GUI:
Display windowDisplay =
new Display(window, null, "Graphics");
windowDisplay identifier for the Display object where the BufferedPanel will be placed
window identifier for the BufferedPanel object
"Graphics" title for the Display
Action methods will use the BufferedPanel by extracting its Graphics2D graphics context and adding graphics objects to it
Graphics2D extractor (inside the action method):
Graphics2D G = window.getBufferGraphics();
G identifier for the Graphics2D object
window identifier for the BufferedPanel object
Sample use of the graphics context:
The functions defined in the Graphics2D are called to place graphics objects into the BufferedPanel window
// set paint color to user color choice
G.setPaint(color.getColor());
G identifier for the Graphics2D object
color identifier for the ColorView object
// line to draw - from P1 to P2
Line2D.Double L = new Line2D.Double(P1, P2);
G.draw(L);
G identifier for the Graphics2D object
L identifier for the Line2D.Double object that will be displayed
P1 identifier for the Point2D.Double object that represents the start point of the line
P2 identifier for the Point2D.Double object that represents the end point of the line