ToolTip with Z-Order Problem but no Flickering

   

This is a modification of another applet to fix one of its two problems. 

Problem:  the ToolTip does not appear properly.

Fixed part: In the original applet the ToolTip did not appear at all, of it flickered on only briefly.  Here, the tipCanvas component is setVisible(true) and later setVisible(false) as a workaround for a problem also seen on the Sun JRE 1.4 (Sun bug ID: 4968008), which was fixed by Sun JRE 1.5 beta 1.  This allows the ToolTip to appear.

Part still broken in early Mac Java 1.4 versions but fixed in later versions:  the z-order of the components is wrong, with the ToolTip appearing behind the component.  This seems similar to the simpler bug here.

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 tooltip5 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 tooltip5


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);
    tipCanvas.setVisible(false);
    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);
    }
    tipCanvas.setVisible(true);
}

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