This issue presents tips, techniques, and sample code for the following topics:
Notice: To make it easier to identify specific issues of
Tech Tips, we are using the publishing date only. We are
no longer using volume and number to identify issues of
Tech Tips.
Custom Carets
In the JavaTM programming language, the term "cursor" refers
to a visual location indicator that is typically set by the mouse. The
term "caret" refers to a location indicator used while
inserting text. A cursor set by the mouse is commonly rendered as a
pointer, while a caret is often drawn as a thin vertical line between
text characters.
In the Java 2 platform, there's a new feature that allows you to define
custom carets, that is, carets of different shapes. To see how this
works, let's look at a short example:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.text.*;
class MyCaret extends DefaultCaret {
// draw the caret
public void paint(Graphics g) {
if (!isVisible())
return;
try {
JTextComponent c = getComponent();
int dot = getDot();
Rectangle r = c.modelToView(dot);
g.setColor(c.getCaretColor());
g.drawLine(r.x, r.y + r.height - 1,
r.x + 3, r.y + r.height - 1);
}
catch (BadLocationException e) {
System.err.println(e);
}
}
// specify the size of the caret for redrawing
// and do repaint() -- this is called when the
// caret moves
protected synchronized void damage(Rectangle r) {
if (r == null)
return;
x = r.x;
y = r.y + r.height - 1;
width = 4;
height = 1;
repaint();
}
}
public class caret {
public static void main(String args[]) {
JFrame frame = new JFrame("Caret demo");
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
JTextArea area = new JTextArea(10, 40);
area.setCaret(new MyCaret());
JPanel panel = new JPanel();
panel.add(area);
frame.getContentPane().add("Center", panel);
frame.pack();
frame.setVisible(true);
}
}
A Caret interface is defined in Java Foundation Classes (JFC)TM
Project Swing components. The interface specifies caret properties such
as paint and setBlinkRate methods.
DefaultCaret is an implementation of this interface.
To define a custom caret, you extend a subclass, MyCaret ,
from this superclass.
To draw the caret, you need to first determine the current X,Y location.
You do this by obtaining the current caret location as an offset into
the text (getDot ). This location is then converted into an
X,Y position using modelToView . In other words, one way of
describing the position of the caret in some text is as a character
offset into the text. Another, lower-level, approach describes the
position as an X,Y coordinate on the screen. To draw the caret, the
screen coordinate is required.
The caret is rendered as a horizontal line with width 4 and height 1,
below and to the left of the current character.
In addition to the paint method for MyCaret , there's another
important method that you need to include, the damage method.
If you remove the damage method from the example above, you
will notice that moving the cursor leaves debris, that is, stray pixels.
The damage method specifies the bounding box for the custom
caret drawn by paint . Without this method, the text area is
not correctly refreshed as the caret moves. So the damage method is
called repeatedly.
You can use the custom caret feature to define different types of
carets, such as an I-beam caret.
Reference Objects
In the Java programming language, the term "reference" usually
refers to addresses of objects, for example, in passing an object
argument (by reference) to a method that has a reference parameter.
Java 2 software introduces another use of the term, the Reference class.
An object of one of the Reference classes (WeakReference ,
SoftReference , PhantomReference ) contains
a "referent." The referent is an arbitrary Java object of
any type. In other words, a Reference object is a wrapper for a
reference. It's somewhat analogous to an Integer object being a
wrapper for an integer.
The reason why this feature is important is that the Java garbage
collector knows about the Reference classes, and interacts with
them. To see how this works, consider an example:
import java.lang.ref.*;
public class ref {
static Reference weakref;
static void f() {
String s = new String("abc");
weakref = new WeakReference(s);
}
public static void main(String args[]) {
// create garbage (a String with no references to it)
f();
System.out.println("Before GC = "
+ weakref.get());
// run garbage collector until no
// more memory freed up
Runtime rt = Runtime.getRuntime();
long free = rt.freeMemory();
long oldfree;
do {
oldfree = free;
rt.gc();
free = rt.freeMemory();
} while (free > oldfree);
System.out.println("After GC = "
+ weakref.get());
}
}
This program starts up and immediately calls method f ,
which in turn, creates a string.
There are situations where an application would like to have some
control over the process of garbage collection, and the Reference
classes offer this. In the example above, a WeakReference
object is set up, with the string as its referent. When the method
returns, the string is garbage (except for the WeakReference
object referring to it). But the garbage collector has not run yet,
and so the referent of the WeakReference object is
accessible via the get method. Then the garbage collector runs,
iterating until no additional memory is freed. The referent is checked
again, and this time it's null. In other words, when garbage collection
occurs, the referent is "cleared."
It's also possible to specify a queue for the Reference object. The
Reference object is added to the queue ("enqueued") at some
point after the referent is cleared.
This might not seem like very much, but it's quite useful in a
variety of applications. For example, one of the collection classes
in the Java 2 platform, WeakHashMap , makes use of
WeakReference objects. A WeakHashMap has
the property that keys in the map are discarded when no longer in
use. Or to say it more precisely, unused keys are subject to being
discarded when the garbage collector runs. Conceptually, this mechanism
is implemented by using a WeakReference object as a
wrapper on the actual key, and then periodically examining a queue of
WeakReference objects whose referents (the actual keys)
have been cleared by the garbage collector.
Another example is the use of SoftReference objects,
whose referents are cleared before the Java1 Virtual Machine throws
an OutOfMemory error. You can use this type of Reference
object to implement caches, where a cached data structure is normally
saved, but may be given up by the garbage collector in response to
memory demand.
The JDC Tech Tips are written by Glen McCluskey.
_______
1 As used on this web site, the terms
"Java virtual machine" or "JVM" mean a virtual machine for the Java platform.
|