I've seen a number of posters argue that Swing components should not be extended, and that functionality should instead be added via composition. So say I want to reusably create a JPanel
with absolute positioning (no layout manager) in which I can reposition components with the mouse:
public class MoveableComponentPanel
{
private final JPanel m_panel;
public MoveableComponentPanel()
{
m_panel = new JPanel(null);
}
public void add(Component c)
{
m_panel.add(c);
c.addMouseListener(m_mover);
c.setSize(c.getPreferredSize());
}
private final MouseListener m_mover = new MouseListener()
{
private int m_startX, m_startY;
@Override
public void mousePressed(MouseEvent e)
{
if (e.getButton() == MouseEvent.BUTTON1)
{
m_startX = e.getX();
m_startY = e.getY();
}
}
@Override
public void mouseReleased(MouseEvent e)
{
if (e.getButton() == MouseEvent.BUTTON1)
{
Component c = e.getComponent();
Point p = c.getLocation();
p.x += e.getX() - m_startX;
p.y += e.getY() - m_startY;
c.setLocation(p);
c.repaint();
}
}
@Override
public void mouseClicked(MouseEvent e) {}
@Override
public void mouseEntered(MouseEvent e) {}
@Override
public void mouseExited(MouseEvent e) {}
};
}
Looks nice, but there's no way to add the panel to a container. Further headaches if I want to allow a calling class to interact with the panel, e.g. change size, background color, register event listeners, etc. Either I add a getPanel()
accessor, which breaks encapsulation, or write pass-through methods for the JPanel
methods/properties I want to expose (potentially many). Is there some other strategy I'm missing here? What is the accepted best practice?