1

How do I copy a Swing component, while keeping its properties? I've tried this by using the clone() method, but it fails with an error:

clone() has protected access in java.lang.Object

How should I copy a Swing component using code?

This is my code currently:

 public void copy_component() throws CloneNotSupportedException {

    Component[] components = design_panel.getComponents();

    for (int i = 0; i < components.length; i++) {

        boolean enable = components[i].isEnabled();

        if (enable == true) {

            JButton button = components[i].clone();
            design_panel.add(button);
        }
    }
}
Michael Berry
  • 70,193
  • 21
  • 157
  • 216
  • 3
    Write a copy constructor. Do not use `Cloneable` [since it is broken by desing](https://www.artima.com/intv/bloch13.html). – Turing85 Apr 30 '18 at 13:12
  • https://stackoverflow.com/questions/3913199/cloning-a-swing-component – guleryuz Apr 30 '18 at 13:13
  • 2
    *"How do I copy a Swing component.."* Why would you want to? As opposed to, say, having two components share the same model. See [What is the XY problem?](http://meta.stackexchange.com/q/66377) – Andrew Thompson Apr 30 '18 at 14:54

1 Answers1

3

Cloneable is broken and shouldn't be used - its architecture was essentially mistaken, and it's only there for backwards compatible reasons.

The normal approach these days is to use a copy constructor, which you can define on your own object (or sometimes define a utility method to clone a separate object.) However, if you're using lots of different Swing components this would be a bit of a pain.

The other approach is to serialize an object back and forth in place, which has the effect of creating a deep cloned object. It's a bit of a hack, and will only work when objects are Serializable, but since Swing components fit this description you can use something like the following:

private Component cloneSwingComponent(Component c) {
    try {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(baos);
        oos.writeObject(c);
        ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
        ObjectInputStream ois = new ObjectInputStream(bais);
        return (Component) ois.readObject();
    } catch (IOException|ClassNotFoundException ex) {
        ex.printStackTrace();
        return null;
    }
}
Michael Berry
  • 70,193
  • 21
  • 157
  • 216