Fire Lancer
Fire Lancer

Reputation: 21

How do I make Graphics2D draw a tooltip on Mouse Hover

so I have initialized each individual vertex as a JLabel and drawn the dot on the application with Graphics2D. However, I can't get a mouse listener to work with the graphic drawing for some reason. I am trying to get a tooltip to appear whenever the user has their mouse on the point (making an interractive graph).

package GUI;

    import java.awt.Color;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.event.MouseEvent;
    import java.awt.event.MouseMotionListener;

    import javax.swing.JLabel;

    @SuppressWarnings("serial")
    public class Vertex extends JLabel {

    int x;
    int y;
    private int pointWidth;


    public Vertex(int x, int y, int pointWidth, Graphics2D g2) {

        g2.fillOval(x, y, pointWidth, pointWidth);

        //This above works

        setLocation(x, y);
        setSize(pointWidth, pointWidth);

        addMouseMotionListener(new MouseMotionListener() {
            @Override //This below doesn't work, but it does print out correct coordinates
            public void mouseMoved(MouseEvent event) {
                //double x = event.getPoint().getX();
                //double y = event.getPoint().getY();
                System.out.println(x+pointWidth/2+"    "+y+pointWidth/2);

                //Graphics g2 = getGraphics();

                g2.setColor(new Color(0,0,0,250));
                g2.fillRect(x, y, 100, 100);

                g2.dispose();
            }

            @Override
            public void mouseDragged(MouseEvent event) {
                //do nothing idc
            }
        });

    }

    public int getPointWidth() {
        return pointWidth;
    }

    public void setPointWidth(int pointWidth) {
        this.pointWidth = pointWidth;
    }

}

I am hoping to get information written on the tooltip, so if you could give me information on how to draw it with text on it? Or maybe I have to initialise the tooltip as a panel? I am not sure, I need help with that

Upvotes: 0

Views: 2298

Answers (1)

MadProgrammer
MadProgrammer

Reputation: 347332

It's hard to know exactly what to suggest, but lets start with the fact the Swing components support tooltip text out of the box, see How to Use Tool Tips

This would suggest that all you really need to do is call setToolTipText and let the system do the rest.

However, based on the available code, I think you're abusing JLabel. Personally, I'd start with a JPanel, it's much more flexible and does't have the same overhead and complexity that JLabel does.

I would then start with a concept of a Vertex, which just holds information about the point

public class Vertex {
    private Point point;

    public Vertex(Point point) {
        this.point = point;
    }

    public Point getPoint() {
        return point;
    }

    @Override
    public String toString() {
        return "Vertex @ " + getPoint().x + "x" + getPoint().y;
    }

}

I'd then create some kind of "drawable" concept which can draw the Vertex the way you want to do (I like to decouple these things)

For me, I'd simply extend a Ellipse2D.Double to draw the Vertex, it is self drawing and has collision detection capabilities built in, very important for what you want to achieve.

public class VertexPoint extends Ellipse2D.Double {
    private Vertex vertex;

    public VertexPoint(Vertex vertex) {
        super(vertex.getPoint().x - 5, vertex.getPoint().y - 5, 10, 10);
        this.vertex = vertex;
    }

    public Vertex getVertex() {
        return vertex;
    }

}

I'd then simply override the getToolTipText(MouseEvent) and paintComponent methods, these would provide the core functionality needed to achieve (what I believe) is you core result...

@Override
public String getToolTipText(MouseEvent event) {
    for (VertexPoint vp : verticies) {
        if (vp.contains(event.getPoint())) {
            return vp.getVertex().toString();
        }
    }
    return null;
}

protected void paintComponent(Graphics g) {
    super.paintComponent(g);
    Graphics2D g2d = (Graphics2D) g.create();
    for (VertexPoint vertex : verticies) {
        g2d.fill(vertex);
    }
    g2d.dispose();
}

As you can see, VertexPoint has a cool contains(Point) method, which can easily be used to determine if (in this case) the mouse is over a vertex or not.

Runnable example...

Because that's a nice bunch of out of context mumbo-jumble

Tooltip hover

import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.geom.Ellipse2D;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Test {

    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class Vertex {
        private Point point;

        public Vertex(Point point) {
            this.point = point;
        }

        public Point getPoint() {
            return point;
        }

        @Override
        public String toString() {
            return "Vertex @ " + getPoint().x + "x" + getPoint().y;
        }

    }

    public class TestPane extends JPanel {

        private List<VertexPoint> verticies;

        public TestPane() {
            verticies = new ArrayList<>(25);
            Random rnd = new Random();
            for (int index = 0; index < 10; index++) {
                int x = rnd.nextInt(200 - 10);
                int y = rnd.nextInt(200 - 10);
                add(new Vertex(new Point(x, y)));
            }
            setToolTipText("");
        }

        public void add(Vertex vertex) {
            verticies.add(new VertexPoint(vertex));
        }

        @Override
        public String getToolTipText(MouseEvent event) {
            for (VertexPoint vp : verticies) {
                if (vp.contains(event.getPoint())) {
                    return vp.getVertex().toString();
                }
            }
            return null;
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            for (VertexPoint vertex : verticies) {
                g2d.fill(vertex);
            }
            g2d.dispose();
        }

        public class VertexPoint extends Ellipse2D.Double {
            private Vertex vertex;

            public VertexPoint(Vertex vertex) {
                super(vertex.getPoint().x - 5, vertex.getPoint().y - 5, 10, 10);
                this.vertex = vertex;
            }

            public Vertex getVertex() {
                return vertex;
            }

        }

    }

}

Upvotes: 2

Related Questions