views:

306

answers:

2

I have an AWT canvas (3rd party library) that displays some information. I need to display a scroll pane over top of it. Since the canvas is AWT, I need to use a ScrollPane instead of a JScrollPane. I'd like to give the scrollpane a rounded border - is that at all possible in AWT? Or is there any way I can use a JScrollPane on top of the canvas and still have it show up (I think the latest version of Java supports better mixing of lightweight/heavyweight components, but let's assume that's not an option).

Thanks, Jeff

A: 

"Since the canvas is AWT, I need to use a ScrollPane instead of a JScrollPane."

Why is this? I think you can use a JScrollPane.

Canvas extends java.awt.Component, and there is a constructor JScrollPane(java.awt.component component)

Fortega
The canvas isn't going in the scrollpane. The scrollpane is part of a popup component that sits on top of the canvas.
Jeff Storey
A: 

I initially toyed around with the idea of using a JScrollPane inside a JPopupMenu with setLightWeightPopupEnabled(false). However, this pops up in a new top-level window above the component - so any rounded borders are drawn on top of the top-level window. It looks like a gray rectangle with the JScrollPane drawn on top with rounded borders.

Then I thought about putting the ScrollPane into a Panel that could handle drawing the rounded border around it. Unfortunately, AWT components don't have the setOpaque() property like Swing components do, so they are rectangular. I could copy the same background color as the parent, but if you wanted to display this on top of some data, it would be pretty obvious.

The compromise approach I finally came up with was to have the Container component paint the border around the ScrollPane child. This is definitely more of a hack-y solution, but it's the only one so far that's worked... here's the final code:

package stackoverflow;

import java.awt.Color;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.List;
import java.awt.Panel;
import java.awt.Rectangle;
import java.awt.ScrollPane;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

public class CanvasPopup {

    public static void main(String[] args) {
        final Frame f = new Frame("CanvasPopup");
        final ScrollPane scroll = new ScrollPane();
        final Panel c = new Panel(null) {
            @Override
            public void paint(Graphics g) {
                g.setColor(Color.GREEN);
                g.fillRect(0, 0, getWidth(), getHeight());

                if (scroll.isVisible()) {
                    g.setColor(Color.RED);
                    Rectangle bounds = scroll.getBounds();
                    g.fillRoundRect(bounds.x - 10, bounds.y - 10, 
                            bounds.width + 20, bounds.height + 20, 15, 15);
                }
            }
        };

        final List list = new List();
        for (int i = 0; i<100; i++) {
            list.add("Item " + i);
        }
        scroll.add(list);
        scroll.setBounds(75, 75, 150, 150);
        scroll.setVisible(false);
        c.add(scroll);

        c.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                if (!scroll.isVisible()) {
                    scroll.setLocation(e.getPoint());
                }
                scroll.setVisible(!scroll.isVisible());
                c.repaint();
            }
        });
        f.add(c);

        f.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                System.exit(0);
            }
        });
        f.setSize(300, 300);
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }

}  
Nate