-2

I'm trying to map data flow between some server hosts. The idea is that data flows between multicast sessions in a network, and I have a table of where the data goes from and to. I want to generate diagrams showing what goes where using arrows.

I've drawn a few shapes (rectangles for hosts, and ovals for multicast sessions) using the Graphics library and stored the position/scale data of the shapes in objects so I can calculate where the arrows should latch on. I have also made arrows between them. The arrows are added using a custom function with the paintComponenet method, sort of like addArrow(startShape, endShape), which will find the two nearest anchor points of the shapes and draw the arrow between them.

My work so far, randomly using the addArrow function

However, this is very lifeless in itself. I also want to add a hover effect to the arrows, so that it thickens and displays some custom text when the mouse pointer touches it. This doesn't seem viable using the paintComponent function, since I can't add events to the shapes it draws.

I think it would be possible to draw the arrows, then put them into a JLabel component and define mouse events on that. I may also be able to create a new "arrow swing component", but I think that's above my level right now.

Do you guys have a recommendation for how to proceed?

Pepe
  • 7
  • 1
  • I think you need to listen to the mouse events on the canvas and then from the xy position of the event calculate your self if that falls within the bounds of any of the shapes you are drawing. – bhspencer Sep 21 '18 at 17:37
  • Typically when I have done this I create a class for each of the objects I want to draw. I give each of those objects a draw() method and a containsPoint(x, y) method. Then to draw your image you iterate over your collection of objects calling the draw() method on each. Your objects have to know their position and also state such as isSelected etc... – bhspencer Sep 21 '18 at 17:45
  • your work so far is a diagram - good luck continuing that diagram – gpasch Sep 21 '18 at 18:54
  • @gpasch Yes it is a diagram, generated from code using the Graphics library, thats kind of the whole point :P My question was about how possible it is to add events to the drawn shapes. I can add the code if you really want it, but I didn't feel like that would help too much as believe I already explained the problem clearly. – Pepe Sep 21 '18 at 22:12
  • *"This doesn't seem viable using the paintComponent function"* - It is, but you need to provide information to the model so it knows what to do. This means you need to employ a `MouseListener` and possibly a `MouseMotionListener`. You should also investigate the `getTooltipText` methods of `JComponent` – MadProgrammer Sep 21 '18 at 23:42
  • I'd start by breaking your issues down into manageable chunks, solve one problem at a time and form a design from them. You could start with something like [Connect two circles with a line](https://stackoverflow.com/questions/47369565/connect-two-circles-with-a-line/47371140#47371140) and [How to draw 2d arrows with Java Swing?](https://stackoverflow.com/questions/30991742/how-to-draw-2d-arrows-with-java-swing/30992415#30992415) – MadProgrammer Sep 21 '18 at 23:46
  • Then maybe you could have a look at [How do I make Graphics2D draw a tooltip on Mouse Hover](https://stackoverflow.com/questions/50547097/how-do-i-make-graphics2d-draw-a-tooltip-on-mouse-hover/50547402#50547402) and [this example](https://stackoverflow.com/questions/34344309/create-a-swing-gui-to-manipulate-png-pixel-by-pixel/34346818#34346818) for more ideas about how to implement tooltips through a single component – MadProgrammer Sep 21 '18 at 23:48
  • The reality is, none of your "problems" are unique and, in of themselves, have been solved before, you just need to find away to incorporate them into your design – MadProgrammer Sep 21 '18 at 23:49

1 Answers1

-1

I think it would be possible to draw the arrows, then put them into a JLabel component and define mouse events on that.

Yes. You just create an Icon to represent the Arrow and than add the Icon to the label.

There are a couple of ways to create the Icon.

You can actually implement the Icon interface:

import java.awt.*;
import javax.swing.*;

public class ColorIcon implements Icon
{
    private Color color;
    private int width;
    private int height;

    public ColorIcon(Color color, int width, int height)
    {
        this.color = color;
        this.width = width;
        this.height = height;
    }

    public int getIconWidth()
    {
        return width;
    }

    public int getIconHeight()
    {
        return height;
    }

    public void paintIcon(Component c, Graphics g, int x, int y)
    {
        g.setColor(color);
        g.fillRect(x, y, width, height);
    }

    public static void main(String[] args)
    {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }

    public static void createAndShowGUI()
    {
        JPanel panel = new JPanel( new GridLayout(2, 2) );

        for (int i = 0; i < 4; i++)
        {
            Icon icon = new ColorIcon(Color.RED, 50, 50);
            JLabel label = new JLabel( icon );
            label.setText("" + i);
            label.setHorizontalTextPosition(JLabel.CENTER);
            label.setVerticalTextPosition(JLabel.CENTER);
            panel.add(label);
        }

        JFrame f = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.getContentPane().add(panel);
        f.setSize(200, 200);
        f.setLocationRelativeTo( null );
        f.setVisible(true);
    }
}

Or, you can paint onto a BufferedImage and use the image to create in ImageIcon:

BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
Graphics g = bi.getGraphics();
g.setColor(...);
g.fillOval(...);
ImageIcon icon = new ImageIcon( bi );

Of course one of the problems with this is that the Icon is always rectangular so the events are generated even when a bit outside the arrow.

You could try using the Shape Component found in Playing With Icons

camickr
  • 321,443
  • 19
  • 166
  • 288
  • The shape component usage in the guide you linked seem perfect! I'll try it out immediately, thanks! :) – Pepe Sep 22 '18 at 05:45