views:

21

answers:

1

I have been trying to find a way (in Swing) to connect two JInternalFrames with a CubicCurve2D (otherwise known as a cubic bezier curve). The overall effect I'm trying to achive is an interface similar to Yahoo! Pipes (the curve should go from the bottom of one internal frame to the top of the other).

Has anybody here done this before? The issue I am running into is that I cannot figure how to draw an updating curve in a way which is visible to the user. Drawing to and then repainting JDesktopPane.getGraphics doesn't seem to do anything.

If possible, I would like to use an offscreen buffer.

+2  A: 

Yes. Here's an example using drawLine(int x1, int y1, int x2, int y2), but invoking draw(Shape s) on your curve is a straightforward extension. You may have to expand the ComponentAdapter to handle resize events, too.

alt text

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Stroke;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import javax.swing.JDesktopPane;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;

/** @see http://stackoverflow.com/questions/3951383 */
public class JDPTest extends JDesktopPane {

    private static final Stroke s = new BasicStroke(4.0f);
    private MyFrame one = new MyFrame("One", 100, 100);
    private MyFrame two = new MyFrame("Two", 400, 240);

    public JDPTest() {
        this.setPreferredSize(new Dimension(640, 480));
        this.add(one);
        this.add(two);
    }

    @Override
    protected void paintComponent(Graphics g) {
        Graphics2D g2d = (Graphics2D) g;
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
            RenderingHints.VALUE_ANTIALIAS_ON);
        g2d.setColor(Color.lightGray);
        g2d.fillRect(0, 0, getWidth(), getHeight());
        g2d.setColor(Color.blue);
        g2d.setStroke(s);
        int x1 = one.getX() + one.getWidth() / 2;
        int y1 = one.getY() + one.getHeight() / 2;
        int x2 = two.getX() + two.getWidth() / 2;
        int y2 = two.getY() + two.getHeight() / 2;
        g2d.drawLine(x1, y1, x2, y2);
    }

    private final class MyFrame extends JInternalFrame {

        MyFrame(String name, int x, int y) {
            super(name);
            this.setSize(160, 100);
            this.setLocation(x, y);
            this.setVisible(true);
            this.addComponentListener(new ComponentAdapter() {

                @Override
                public void componentMoved(ComponentEvent e) {
                    JDPTest.this.repaint();
                }
            });
        }
    }

    private void display() {
        JFrame f = new JFrame("JDPTest");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.add(this);
        f.pack();
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                new JDPTest().display();
            }
        });
    }
}
trashgod
I don't have time to try it out right now but thank you for the screenshot! I'll take that as proof enough to accept this as the correct answer.
npsken
trashgod