# GUI-Komponenten dynamisch erzeugen



## RealHAZZARD (20. März 2006)

Servus.

Ich habe vor Teile meiner GUI zur Laufzeit zu erweitern.
Nur stehe ich son einbisschen auf dem Schlauch, wie ich das machen soll?!
Ich weiß nicht recht, wie ich die Namensvergabe (der Komoponente die ich ins 
Leben rufen will) und das Hinzufügen eines Actionlisteners machen soll?

Hat einer eine Idee?

THX


----------



## takidoso (20. März 2006)

Hallole,
allso ich denke, wenn ich Dich richtig verstehe möchtest Du java-Klassen als sourcecode durch Deine Anwendung erzeugen, die kompiliert werden und dann außerdem gleich von selber Anwendung zugreifbar werden, richtig?
hmmm das klingt sehr spannend. Was Namen angeht, würde ich an Deiner Stelle ein sprechendes Präfix nehmen und dann vielleicht etwas hochzählen. Aber für richtig spannend würde mich die technische Frage beschäftigen wie man etwas compiliert und dann gleich wieder in seine Anwendung einbindet.

Andererseits ist für mich die Frage da, ob Du nicht auch schon weniger reicht. In anderen Worten wie arg flexibel soll denn Deine Einbindung auf neue GUI-Komponenten sein?

Vor einigen Jahren hatte ich mal die (selbstgetstellte) Aufgabe gehabt innerhalb eines recht einfachen Neuronalen-Netzwerk-Editors verscheidene Neuronen (also Knoten im Netz) sehr kompfortabel einzu binden. Dazu musste man nur in einem bestimmten Package ein entsprechendes Interface implementieren, und das Framework durchsuchte dann eincah alle verwendeten bibliotheken nach diesem Paket und Klassen des entsprechenden Typs. Also so richtig dynamisch war es nicht, aber dafür kompfortable.

Vielleicht könnte die Klasse die ich dafür verwendete Dir weiterhelfen...

```
package de.cmk.util;

import java.util.*;

import java.util.zip.*;
import java.util.jar.*;
import java.net.*;
import java.io.*;

import javax.swing.JProgressBar;

/**
* ClassCollector sammelt Klassen einer Gegebenen unter Vorgabe eines
* Unterverzeichnises, welches direkt unter dem Package der gegebenen Klasse
* liegt.
* Diese Klasse ist zum dynamischen Zuladen von Klassen geeignet. Auf diese Weise
* können z.B. Unterdialoge zur Laufzeit einem Übergeordneten Panel zugeordnet werden
*/

public class ClassCollector
{
    Vector m_classNames = new Vector();
    String m_path;
    String m_packageName;
    String m_subPackageName;
    String m_lastQual;
    Class  m_class;



    public ClassCollector(Class klasse, String lastQualifier)
    {
        m_class          = klasse;
        m_path           = m_class.getResource("").getFile();
        m_lastQual       = lastQualifier;
        m_packageName    = m_class.getName().substring(0, m_class.getName().lastIndexOf('.'));
        if (m_lastQual!=null && m_lastQual.length()>0)
        {
            m_subPackageName = m_packageName + '.' + m_lastQual;
        }
        else
        {
            m_subPackageName = m_packageName;
        }

        try
        {
            collectClassNames();
        }
        catch (Exception e)
        {
            MExceptionHandler.handleException(e);
        }
    } // end of ClassCollector(Class, String)

    protected void collectClassNames() throws Exception
    {
        Vector classFileNames = new Vector();

        if (m_class.getResource("").getProtocol().equalsIgnoreCase("jar"))
        {
            URLConnection urlConn = m_class.getResource("").openConnection();
            if (!(urlConn instanceof JarURLConnection))
            {
                throw new Exception("Is jar file but has no JarURLConnection");
            }
            JarURLConnection jarConn = (JarURLConnection)urlConn;
            JarFile jarFile = jarConn.getJarFile();
            for (Enumeration e = jarFile.entries(); e.hasMoreElements(); )
            {
                JarEntry currentEntry = (JarEntry)e.nextElement();
                if (currentEntry.getName().startsWith(m_path)
                    &&!currentEntry.isDirectory())
                {
                    classFileNames.add(currentEntry.getName());
                } // end of if
            } // end of for e
        } // end of if(Classe in einer .jar Datei)
        else
        {
            URL url;

            url = m_class.getResource("/"+m_subPackageName.replace('.','/'));
//            System.out.println("2. url="+url.toString());
            if (url==null)
            {
                throw new Exception("Kann "+m_lastQual+" Verzeichnis nicht finden"+
                                    "\nres="+m_class.getResource(""));
            }
            File demosDir = new File(url.getFile());

            if (demosDir==null)
            {
                throw new Exception("Kann "+m_lastQual+" Verzeichnis nicht finden"+
                                    "\n url="+url);
            }

            if (!demosDir.isDirectory())
            {
                throw new Exception(m_lastQual+" ist kein Verzeichnis"+
                                    "\n url="+url+
                                    "\n file="+demosDir);
            }
            String[] list = demosDir.list();

            for (int i = 0; i<list.length; i++)
            {
                String fullName = m_subPackageName+"."+list[i];
                classFileNames.add(fullName);
            }
        } // end of if else (Classe in einer .jar Datei)

        for (int i = 0; i<classFileNames.size(); i++)
        {
            String currentName = (String)classFileNames.get(i);
            if (currentName.indexOf("$")==-1 && currentName.endsWith(".class"))
            {
                // remove trailing ".class"
                currentName = currentName.substring(0, currentName.length()-6);
                StringBuffer tmp = new StringBuffer(currentName);
                for (int j = 0; j<tmp.length(); j++)
                {
                    if (tmp.charAt(j)=='/'||tmp.charAt(j)=='\\')
                        tmp.setCharAt(j, '.');
                }
                m_classNames.add(tmp.toString());
            }
        }

    } // end of collectClassNames()

    public List loadClasses(JProgressBar progressBar)
    {
        List loadedClasses = new ArrayList();
        int count = progressBar.getValue();

        for (int i = 0; i<m_classNames.size(); i++)
        {
            String className = (String)m_classNames.get(i);
            String progressName = className.substring(m_subPackageName.length()+1,
                className.length());
            progressBar.setValue(count++);
            progressBar.setString("Lade "+progressName);
            try
            {
                Class currentClass = Class.forName(className);
                Object obj = currentClass.newInstance();

                if (m_class.isInstance(obj))
                {
                    loadedClasses.add(obj);
                }

            }
            catch (Exception e)
            {
                MExceptionHandler.handleException(e);
            }
        }
        return loadedClasses;
    } // end of loadClasses(JProgressBar)

    public List loadClasses()
    {
        List loadedClasses = new ArrayList();

        for (int i = 0; i<m_classNames.size(); i++)
        {
            try
            {
                Class currentClass = Class.forName((String)m_classNames.get(i));
                if (!currentClass.isInterface())
                {
                    Object obj = currentClass.newInstance();
                    if(m_class.isInstance(obj))
                    {
                        loadedClasses.add(obj);
                    }
                }
            }
            catch (Exception e)
            {
                MExceptionHandler.handleException(e);
            }
        }
        return loadedClasses;
    } // end of loadClasses()

    public String[] getClassNames()
    {
        return (String[])m_classNames.toArray((Object[])new String[0]);
    }

    public String getClassName(int i)
    {
        return (String)m_classNames.get(i);
    }

} // end of ClassCollector
```

mal ne andere neugierige Frage, in wie weit muss denn eigetnlich der Anwender Deines Programms etwas vo Java-GUI-Entwicklung verstehen?

Takidoso


----------



## RealHAZZARD (20. März 2006)

Holla.

Tausend Dank schonmal, aber
das ist etwas zu viel des Guten.
So kompliziert sollte das garnicht aufgebaut sein.
Mal Praktisch gesprochen:
Ich habe ein JMenu. Und das kann eben zur Laufzeit noch ein
paar MenuItems hinzubekommen. Denen wiederum muss ich 
ja auch einen ActionListener zukommen lassen.

Ich habe die Frage so allgemein gestellt, weil mich auch gleich 
interessieren würde, wie man es schafft einen (nur z.B.) JButton
zu Laufzeit zu ins Leben zu rufen, den ich hinterher mit Namen 
ansprechen kann. 

Die Frage ob der Anwender etwas von GUIs verstehen muss ist damit 
,glaube ich, auch beantwortet.  

Das hat sich aber eh erledigt. Ich hab alle in nen vector gepackt, und 
kann die jetzt darüber erreichen.


----------



## takidoso (20. März 2006)

Ahhh ch soooo,
dann hatte ich Deine Anfrage missinterpretiert.
Also wenn Menuepunkte z.B. wegen Berechtigungen oder anderen Situationen angezeigt werden sollen und ausgrauen nicht ausreicht, würde ich einen Listener basteln, der sich and das Erscheinen des Menüs orientiert. Ich denke da gibt es sicher irgendeinen Event. Wenn die Bedingung dann zutrifft wird halt das MenuItem dazu gebracht.
Das schöne an zumindest Swing ist, dass im vollen Lauf Gui-Elemente dazu oder entfernt werden können. Vermutlich geht das mit SWT und AWT genauso, doch da habe ich nicht so arge Aktien drinne.

Takidoso


----------



## RealHAZZARD (20. März 2006)

Na ich hab das jetzt mal so gemacht:

```
connection_list.removeAllElements();//Der Vector
            for (int i=1;i<_connectionframe.con_Names.length;i++)
            {
                connection_list.add(new JMenuItem(
                        _connectionframe.con_Names[i]));
                connection_list.get(i).setActionCommand("MenCon"+String.valueOf(i));
                _menu_connect.add(connection_list.get(i));
            }
```


----------

