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);
}
}