Über Liste verschiendene JComponents mit eigenem implementierten Interface ansprechen

markusk21

Mitglied
Guten Abend,
Ich möchte einen wiederverwendbaren Dialog programmieren, der abhängig von einer überlieferten Klasse passende JComponents enthält, mit der alle setter und getter der überlieferten Klasse über Reflection manipuliert werden können.

Das funktioniert auch ganz gut, ich stelle per Reflection fest, was der Typ der Eigenschaft ist und nehme dann eine passende JComponent in den Dialog auf.
Z.B. für ein Int einen JSpinner:
Java:
public static JComponent getComponent(Class c, Object value){
        
        if (c.isInstance(new Integer(3))){
            JSpinner sp = new JSpinner(new SpinnerNumberModel(Integer.parseInt(value.toString()), 0, Integer.MAX_VALUE, 1));
            
            return sp;
        }
}

Jetzt muss nur der Dialog natürlich, unabhängig davon ob es ein JSpinner, ein JTextField oder ein Button zum Setzen einer java.awt.Color, auf eine Änderung der Werte reagieren. Dummerweise haben JButton, JTextField und JSpinner keine gemeinsame Methode oder gar Listener um auf die Änderungen zu reagieren.

Also will ich die Klassen überschreiben, die alle das selbe Interface implementieren, ganz einfach:
Java:
public interface ValueComponent {
    Object getValue();
    void addValueChangeListener(ValueChangeListener l);
}

So weit so gut. Im Dialog kann ich nun eine Liste von JComponents halten, und die im Dialog darstellen.
JComponents implementieren natürlich nicht mein schönes Interface.
Ein Valuecomponent kann ich jedoch nicht dem Dialog hinzufügen.

Ich hoffe, ich hab das verständlich ausgedückt.
Mein Versuch sah so aus, ich mache eine JComponent-Klasse, die das Interface implementiert und kann dann button, Spinner oder was auch immer für beide Funktionen benutzen:

Java:
public class JValueComponent extends JComponent implements ValueComponent {

    @Override
    public Object getValue() {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public void addValueChangeListener(ValueChangeListener l) {
        throw new UnsupportedOperationException("Not supported yet.");
    }
    
}

Ein eigener JSpinner, der das interface implementiert gilt aber scheinbar nicht als JValueComponent:
Java:
public static JValueComponent getComponent(Class c, Object value){
        
        if (c.isInstance(new Integer(3))){
            JValueSpinner sp = new JValueSpinner(new SpinnerNumberModel(Integer.parseInt(value.toString()), 0, Integer.MAX_VALUE, 1));
            
            return sp;
        }   
}
die Methode meckert sich entsprechend über "incompatible Types" in Zeile 6.

Bleibt die einzige Möglichkeit 2 Listen zu führen, eine mit JComponents und eine mit den ValueComponent?
Kann da jemand helfen? Wie kann ich sowas realisieren? Oder denke ich grad zu kompliziert?
 
Java:
public class JValueComponent extends JComponent implements ValueComponent {

    @Override
    public Object getValue() {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public void addValueChangeListener(ValueChangeListener l) {
        throw new UnsupportedOperationException("Not supported yet.");
    }
    
}

Ein eigener JSpinner, der das interface implementiert gilt aber scheinbar nicht als JValueComponent:
Ist klar, denn das Interface alleine hat ja nichts mit JValueComponent zu tun, was du brauchst ist dann
Java:
public class JValueSpinner extends JValueComponent { ... }

das sollte doch dem entsprechen was du vorhast.
[EDIT]Ah zu schnell gedacht .. dann fehlt dir natürlich die Möglichkeit von JSpinner zu erben :/[/EDIT]
 
was spricht gegen:
Java:
public class JValueSpinner extends JSpinner implements ValueComponent { ... }

Dann musst zur Not eben casten. Oder ich versteh das Problem noch nicht ganz 😀
 
@diggaa1984: Stimmt, hab ich vergessen zu beschreiben, war aber auch eine meiner Ideen. Aber schön, dass ich mich scheinbar halbwegs verständlich machen konnte.

Mein momentaner Ansatz ist ValueComponents in der Liste zu halten und nur, beim Hinzufügen zum Dialog nach JComponent zu casten.

Funktioniert, aber ich wäre sehr sehr dankbar, wenn jemand eine elegante Lösung wüsste.
 
grob gesprochen hast du also soetwas??
Java:
public interface ValueComponents { .. }

public class JValueSpinner extends JSpinner implements ValueComponent { .. }
public class JValueTextField extends JTextField implements ValueComponent { .. }
public class JValueComboBox extends JComboBox implements ValueComponent { .. }

List<ValueComponents> l;

l.add(new JValueSpinner(..));
l.add(new JValueTextField(..));
l.add(new JValueComboBox(..));

//und spaeter willst du in etwa folgendes machen (erfordert JComponent als Parameter)
dialog.add(l.get(x));

//und auch
l.get(x).methodeAusInterface();
 
hm dann bin ich ma auf antworten gespannt 🙂

Was stört dich denn an dem cast? Oder wird der Code von anderen verwendet, sodass nicht zwingend JComponents in ihr abgelegt werden?
 

Zurück
Oben