Flickering displaying Canvas

(Apple bug # 3196485)

    This applet is a stripped-down version of ToolTip code, using no threads for purposes of simplicity (click here for the threaded version).  The ToolTip is not displayed properly - typically it flickers on and off.  

    The malfunction here appears to be two problems:

    If you have any insights, workarounds or comments about this test page please contact Mickey Segal.  A listing of  many Java resources is at this link.

Source Code:

import java.applet.*;
import java.awt.*;
import java.awt.event.*;

public class tooltip3 extends Applet {

public void init() 
{
    setBackground(new Color(225,225, 255));
    try
    {
        FrameForApplet frameForApplet = new FrameForApplet("A frame");
    }
    catch (Throwable e)
    {
        System.out.println("Can't use Frame: " + e);
        return;
    }
}

public void paint(Graphics g)
{
    g.drawString("A Frame appears with two Checkboxes with ToolTips", 10 , 25);
}
} // END OF Class tooltip3


final class FrameForApplet extends Frame implements WindowListener, ItemListener {

TipCheck checkbox1, checkbox2;
static Frame frame;
static Insets insets;

FrameForApplet(String s)
{
    super(s);
    setLayout(new GridBagLayout());
    frame = this;
    addNotify();
    insets = getInsets();
    setBounds( 100, 100, 300, 300);
    checkbox1 = new TipCheck("My checkbox 1", new Color(255, 200, 255), Color.black, 
    new Font("Serif", Font.BOLD, 25), "Tooltip 1 text", this);
    constrain(this, checkbox1, 0, 0, 1, 1, 
    GridBagConstraints.NORTH, 0, 0, 0, 0, GridBagConstraints.NONE, 0, 0);
    checkbox2 = new TipCheck("My checkbox 2", new Color(200, 255, 255), Color.black, 
    new Font("Serif", Font.BOLD, 25), "Tooltip 2 text", this);
    constrain(this, checkbox2, 0, 1, 1, 1, 
    GridBagConstraints.NORTH, 10, 0, 0, 0, GridBagConstraints.NONE, 0, 0);
    show();
    addWindowListener(this);
}

static final void constrain(Container container, Component component, int grid_x, int grid_y, 
int grid_width, int grid_height, int anchor, int topPad, int leftPad, int bottomPad, 
int rightPad, int fill, double weightx, double weighty)
{
    GridBagConstraints c = new GridBagConstraints();
    c.gridx = grid_x;
    c.gridy = grid_y;
    c.gridwidth = grid_width;
    c.gridheight = grid_height;
    c.anchor = anchor;
    c.insets.top = topPad;
    c.insets.left = leftPad;
    c.insets.bottom= bottomPad;
    c.insets.right = rightPad;
    c.fill = fill;
    c.weightx = weightx;
    c.weighty = weighty;
    ((GridBagLayout)container.getLayout()).setConstraints(component, c);
    container.add(component);
}

public void windowOpened(WindowEvent we){}

public void windowClosed(WindowEvent we){}

public void windowIconified(WindowEvent we){}

public void windowDeiconified(WindowEvent we){}

public void windowActivated(WindowEvent we){}

public void windowDeactivated(WindowEvent we){}

public void windowClosing(WindowEvent we)
    {
        if (we.getSource() == this)
        {
            setVisible(false);
            dispose();
        }
    }
public void itemStateChanged(ItemEvent ie){}
} // END OF Class FrameForApplet



class TipCanvas extends Canvas {

String tip;

TipCanvas(String tip)
{
    this.tip = tip;
    setFont(new Font("Dialog", Font.PLAIN, 14));
    setBackground(new Color(255, 255, 224)); // light yellow
}

final void setTip(String tip)
{
    this.tip = tip;
}

final Point modifyLocation(Point p)
{
    try
    {
        Dimension toolTipDimension = getSize(); 
        Dimension frameDimension = FrameForApplet.frame.getSize();
        p.x += 4; 
        if (p.x > frameDimension.width - toolTipDimension.width - FrameForApplet.insets.right) 
        p.x = frameDimension.width - toolTipDimension.width - FrameForApplet.insets.right;
        if (p.x < FrameForApplet.insets.left) p.x = FrameForApplet.insets.left;
        int origY = p.y;
        p.y = p.y + 20;
        if (p.y > frameDimension.height - toolTipDimension.height - FrameForApplet.insets.bottom)
        p.y = origY - toolTipDimension.height - 1; 
        return(p);
}
catch (Exception e) 
{
    System.out.println("Error modifying location");
    return (p); 
}
}

public Dimension getPreferredSize()
{
    Graphics g = getGraphics();
    if (g == null) return (new Dimension(0, 0));
    FontMetrics fm = g.getFontMetrics();
    g.dispose();
    System.out.println("getPreferredSize: width = " + fm.stringWidth(tip) + " height = " + fm.getHeight()); 
    return (new Dimension(fm.stringWidth(tip) + 8, fm.getHeight() + 4));
}

public void paint(Graphics g)
{
    Dimension toolTip = getSize();
    System.out.println("paint: width = " + toolTip.width + " height = " + toolTip.height); 
    g.drawRect(0, 0, toolTip.width-1, toolTip.height - 1);
    g.drawString(tip, 4, g.getFontMetrics().getAscent() + 2);
}
} // END OF Class TipCanvas



class TipCheck extends Checkbox implements MouseListener, MouseMotionListener {

TipCanvas tipCanvas;
boolean useTip;
String tip;
Point pointOnFrame;

TipCheck(String label, Color backgroundColor, Color foregroundColor, Font font, String tip, 
Container container)
{
    setLabel(label);
    setBackground(backgroundColor);
    setForeground(foregroundColor);
    setFont(font);
    initTip(tip);
    addItemListener((ItemListener)container);
}

final void initTip(String tip)
{
    this.tip = tip;
    useTip = !tip.equals("");
    addMouseListener(this);
    addMouseMotionListener(this);
}

public void addTip()
{
    tipCanvas = new TipCanvas(tip);
    if (tipCanvas != null) FrameForApplet.frame.add(tipCanvas, 0); 
    if (tipCanvas != null) tipCanvas.setSize(tipCanvas.getPreferredSize()); 
    if (tipCanvas != null) 
    {
        Point tipLocation = tipCanvas.modifyLocation(pointOnFrame);
        tipCanvas.setLocation(tipLocation.x, tipLocation.y);
    }
}

public void removeTip()
{
    if (tipCanvas != null) 
    {
        FrameForApplet.frame.remove(tipCanvas);
        tipCanvas = null;
    }
}

final void setPointOnFrame(int x, int y)
{
    Point frameLocation = FrameForApplet.frame.location();
    Point screenLocation = getLocationOnScreen(); 
    pointOnFrame = new Point(screenLocation.x + x - frameLocation.x, 
    screenLocation.y + y - frameLocation.y);
}

public synchronized void mouseEntered(MouseEvent me)
{
    if (useTip && isShowing()) 
    {
        setPointOnFrame(me.getX(), me.getY());
        addTip();
    }
}

public synchronized void mouseExited(MouseEvent me)
{
    if (useTip && isShowing()) removeTip();
}

public synchronized void mouseReleased(MouseEvent me) {}

public synchronized void mousePressed(MouseEvent me) {}

public synchronized void mouseClicked(MouseEvent me) {}

public synchronized void mouseMoved(MouseEvent me) {}

public synchronized void mouseDragged(MouseEvent me) {}

} // END OF Class TipCheck