Canvas-based component flickers when ToolTip appears in Macintosh Java 1.5

(Apple bug #4129065)

A Frame pops up with two green rectangles representing Canvas-based buttons.  Position the mouse over the the "C" in the upper green button.  A ToolTip appears as expected but the green "buttons" flicker.  The flickering of the underlying component did not occur with Java 1.4 on the Macintosh and does not occur with Sun Java 1.5 for Windows. 

Clearly some change from Mac Java 1.4 to 1.5 resulted in this flickering.  However, since the flickering does not occur when native components such as checkboxes are used (here) it would not be surprising if there were a workaround. 

Note: the flickering referred to in the checkbox example was flickering of the ToolTip, versus here where the flickering is of the components representing Canvas-based buttons.

Note: this ToolTip code is used instead of Java 2 ToolTips in order to support our many Java 1.1 users.

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 tooltip8 extends Applet {

public void init()
{
    setBackground(new Color(225,225, 255));
    try
    {
        FrameForApplet frameForApplet = new FrameForApplet("A frame");
    }
    catch (Throwable e) {return;}
}

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



final class FrameForApplet extends Frame {

TipButton tipButton1, tipButton2;
static Frame frame;

FrameForApplet(String s)
{
    super(s);
    frame = this;
    addNotify();
    setBounds(100, 100, 400, 200);
    setLayout(new GridBagLayout());
    tipButton1 = new TipButton(this);
    constrain(this, tipButton1, 0, 0, 1, 1, GridBagConstraints.NORTH, 0, 0, 0, 0, GridBagConstraints.NONE, 0, 0);
    tipButton2 = new TipButton(this);
    constrain(this, tipButton2, 0, 1, 1, 1, GridBagConstraints.NORTH, 10, 0, 0, 0, GridBagConstraints.NONE, 0, 0);
    show();
}

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);
}
} // END OF Class FrameForApplet



class TipCanvas extends Canvas {

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

public Dimension getPreferredSize()
{
    return (new Dimension(90, 20));
}

public void paint(Graphics g)
{
    g.drawRect(0, 0, 89, 19);
    g.drawString("ToolTip text", 4, 15);
}
} // END OF Class TipCanvas



class TipButton extends Canvas implements MouseListener {

TipCanvas tipCanvas;
Font font;

TipButton(Container container)
{
    font = new Font("Serif", Font.BOLD, 15);
    addMouseListener(this);
}

public synchronized void mouseEntered(MouseEvent me)
{
    tipCanvas = new TipCanvas();
    FrameForApplet.frame.add(tipCanvas, 0);
    Point frameLocation = FrameForApplet.frame.location();
    Point screenLocation = getLocationOnScreen();
    tipCanvas.setSize(tipCanvas.getPreferredSize());
    tipCanvas.setLocation(screenLocation.x + me.getX() + 4 - frameLocation.x,
    screenLocation.y + me.getY() + 15 - frameLocation.y);
}

public synchronized void mouseExited(MouseEvent me)
{
    if (tipCanvas != null)
    {
        FrameForApplet.frame.remove(tipCanvas);
        tipCanvas = null;
    }
}

public synchronized void mouseReleased(MouseEvent me) {}

public synchronized void mousePressed(MouseEvent me) {}

public synchronized void mouseClicked(MouseEvent me) {}

public final Dimension getMinimumSize()
{
    return (new Dimension(100, 20));
}

public final Dimension getPreferredSize()
{
    return(getMinimumSize());
}

public void paint(Graphics g)
{
    g.setColor(Color.green);
    g.fillRect(0, 0, 100, 20);
    g.setColor(Color.black);
    g.setFont(font);
    g.drawString("Canvas text", 10, 15);
}
} // END OF Class TipButton