[Java] Reflection?

Pagina: 1
Acties:

  • Tyf
  • Registratie: December 2002
  • Laatst online: 28-11-2025
Ik moet voor een project een xml doc inlezen en hiervan een gui generen. Dit gedeelte heb ik al voor mekaar gekregen. Het probleem is dat in de xml file ook acties gedefinieerd kunnen zijn die dynamisch ingeladen moeten worden en uitgevoerd. Bv tekst van de ene tekstbox naar de andere copieren.
Ik heb vernomen dat die via reflection zou moeten gebeuren? Maar dit is nog niet mijn belangrijkste probleem voorlopig.
Hoe kan ik een object refereren in java zonder dat daarvan een unieke naam ofzo van gekend is?
Om het probleem wat beter te verstaan. Met volgende code genereer ik de widgets van de gui.
Nu zie je dat elke widget via jcomponent c aangemaakt worden. Maar als ik nu later een eerder gecreeerde textfield wil aanpassen. Hoe kan ik deze dan bereiken? Hij heeft geen naam en het object waarvoor hij gebruikt is is al weer gevuld met een andere widget.
Als ik dit al in orde krijg kan ik beginnen met het reflextion probleem :)
Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
private boolean processWidgetElement(Element e, JComponent container) {
        GridBagConstraints gbc = new GridBagConstraints();
        try {
            gbc.gridx = Integer.parseInt(e.getAttribute("x")) - 1;
            gbc.gridy = Integer.parseInt(e.getAttribute("y")) - 1;
        } catch (NumberFormatException nfe) {
        }
        NodeList nl = e.getChildNodes();
        try {
            int i = 0;
            // avoid the comment Nodes
            while (nl.item(i).getNodeType() != Node.ELEMENT_NODE)
                i++;
            Element wchild = (Element) nl.item(i);
            String label = getLabel(wchild);
            JComponent c;
            if (wchild.getTagName().equals("button")) {
                c = new JButton(label);     
                c.addMouseListener(new java.awt.event.MouseAdapter() {
                    public void mouseReleased(java.awt.event.MouseEvent e) {
                        System.out.println("knop ingedrukt");
                    }
                });

            } else if (wchild.getTagName().equals("textfield"))
                c = new JTextField(label);
            else if (wchild.getTagName().equals("label"))
                c = new JLabel(label);
            else
                return false;
            container.add(c, gbc);
        } catch (NullPointerException npe) {
            return false;
        }
        return true;
    }

[ Voor 4% gewijzigd door curry684 op 02-11-2005 13:42 . Reden: we hebben hier mooie [code] tags die zelfs highlighten.... ]


  • bigbeng
  • Registratie: Augustus 2000
  • Laatst online: 26-11-2021
Ik zou toch met namen gaan werken als ik jou was. Hoe weet je anders naar welk tekstveld je precies wil kopieren?

Mocht het je erom gaan om het vorig gecreeerde element o.i.d., dan kun je die eventueel onthouden in een globale variabele van het type JComponent, of je kunt in de container het laatste component opzoeken:
Java:
1
container.getComponents[container.getComponentCount()-1];


Hiervan kun je met getClass() gegevens over de klasse achterhalen. Kijk vooral in de API documentatie van Sun voor meer informatie.

edit:
Snel code tags gebruiken voordat ik een slap on the wrist krijg van Curry ;)

[ Voor 11% gewijzigd door bigbeng op 02-11-2005 13:47 ]


  • H!GHGuY
  • Registratie: December 2002
  • Niet online

H!GHGuY

Try and take over the world...

je kunt de elementen toch een naam geven...

zoek dan gewoon die uit met de juiste naam.

ASSUME makes an ASS out of U and ME


  • Tyf
  • Registratie: December 2002
  • Laatst online: 28-11-2025
Hoe kan ik deze nu een naam geven @runtime? De namen van de objecten weet je pas op moment dat ze ingelezen worden. Ik ken wel wat java maar om zulke toeren uit te halen?
De naam van de objecten kan eventueel uit de xml file gehaald worden indien dat zou helpen.
Nogmaals ik ken wel wat java maar zoiets heb ik nog nooit moeten doen :(

Het bijhouden van het vorige object is geen mogelijkheid, want het kan evengoed een object zijn dat veel eerder is ingelezen.

[ Voor 19% gewijzigd door Tyf op 02-11-2005 14:36 ]


  • Nick_S
  • Registratie: Juni 2003
  • Laatst online: 22-04 03:55

Nick_S

++?????++ Out of Cheese Error

Dan haal je op runtime je naam uit de XML en stopt deze als key met als value je object in een Map. Dan kun je later adh van de naam weer een Object er bij halen. Moet je alleen wel ergens opslaan, van welk type het een Object is.

'Nae King! Nae quin! Nae Laird! Nae master! We willna' be fooled agin!'


Verwijderd

Nick_S schreef op woensdag 02 november 2005 @ 14:43:
Dan haal je op runtime je naam uit de XML en stopt deze als key met als value je object in een Map. Dan kun je later adh van de naam weer een Object er bij halen. Moet je alleen wel ergens opslaan, van welk type het een Object is.
dat zou je ook in de map kunnen zetten.

  • Tyf
  • Registratie: December 2002
  • Laatst online: 28-11-2025
Hmm nog niet met een map gewerkt, daarjuist even bekeken wel.
Ik was al bezig met het zoeken naar de objecten via de naam.
Bij het inlezen van de objecten (vorige code) heb ik een lijntje toegevoegd "c.setName(naam);"
Deze probeer ik dan te zoeken via volgende code. Nu het werkt nog niet, ben het nog aan het testen ...

Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
    private JComponent zoekOpNaam(String naam, JComponent container)
    {
        JComponent jc = null;
        int aantal = container.getComponentCount();
        int i = 1;
        boolean gevonden = false;
        
        while( i < aantal && gevonden == false)
        {
            System.out.println("while: " + i);
            if (container.getComponent(i).getName().toString() == naam)
                gevonden = true;
            else
                i++;
        }
        return jc;
    }


Ok dit gaat dus niet, heb gemerkt dat de container niet alle items bevat. Kan ze dus niet allemaal overlopen alleen per pannel. Ik zal nu eens kijken naar de Map oplossing.

[ Voor 16% gewijzigd door Tyf op 02-11-2005 16:08 ]


  • Confusion
  • Registratie: April 2001
  • Laatst online: 01-03-2024

Confusion

Fallen from grace

Waarom doe je die toString() op regel 11? getName retourneert zelf al een String.

Wat er aan bovenstaande code niet klopt is dat jc nooit een waarde toegekend krijgt. Je mist een
Java:
1
jc = container.getComponent(i);

(te gebruiken na de 'gevonden = true' (vergeet geen {} te zetten))

[ Voor 17% gewijzigd door Confusion op 02-11-2005 16:16 ]

Wie trösten wir uns, die Mörder aller Mörder?


  • Bluestorm
  • Registratie: Januari 2000
  • Laatst online: 20-08-2022
En niet vergeten dat je Strings niet met == moet vergelijken, maar met equals. (regel 11)

Tenminste... dat [ denk / zie / weet ] ik... | Javascript obfuscator | foto's en video's uploaden


  • Tyf
  • Registratie: December 2002
  • Laatst online: 28-11-2025
ja return waarde van jc was nog niet belangrijk op dat moment. Ik had al via system.out enkele waarden getoond. En de toString(); hehe idd niet nodig.
Thx was vergeten dat het via compare moest :)
Nu het maakt allemaal niet uit via deze methode krijg ik nooit items weer die op een ander pannel staan
juist de naam het pannel.

[ Voor 7% gewijzigd door Tyf op 02-11-2005 16:46 ]


  • Macros
  • Registratie: Februari 2000
  • Laatst online: 25-04 06:43

Macros

I'm watching...

Wanneer je de JComponents maakt, dan stop je ze in een
Java:
1
Map<String, JComponent> namen = new HashMap<String, JComponent>();

Door te doen
Java:
1
2
container.add(c, gbc);
namen.put(wchild.getName(), c);

Dan kan je later dmv. de naam het component weer opvragen.

"Beauty is the ultimate defence against complexity." David Gelernter


  • Tyf
  • Registratie: December 2002
  • Laatst online: 28-11-2025
thx ik dat kan ik wel gebruiken.
Ik heb het het opzoeken van components via de getcomponent nu recursief opgelost, waardoor ik nu wel alle objecten bekijken. Maar dat lijkt me zo'n omslachtige manier.
Ik zal uw stukje code eens proberen
bedankt!

[ Voor 14% gewijzigd door Tyf op 05-11-2005 14:22 ]


Verwijderd

Tyf schreef op zaterdag 05 november 2005 @ 13:51:
thx ik dat kan ik wel gebruiken.
Ik heb het het opzoeken van components via de getcomponent nu recursief opgelost, waardoor ik nu wel alle objecten bekijken. Maar dat lijkt me zo'n omslachtige manier.
het kan makkelijk recursief: (ongetest uit de losse pols)
Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
    private Component findByName(String name, Component container) {
        Component[] components = container.getComponents();
        for (int i = 0; i < components.length; ++i) {
                        if (components[i].getName().equals(name)) {
                                return components[i];
                        }
                        Component comp = findByName(name, components[i]);
                        if (comp != null) {
                                return comp;
                        }
                } 
        return null;
    }


edit:
ikz ie nu dat het niet gaat werken, getComponents komt uit Container. Nouja, kleine aanpassing door de methode signature aan te passen en alleen recursief aanroepen als component een instantie is van Container...

[ Voor 16% gewijzigd door Verwijderd op 05-11-2005 14:38 ]


  • Macros
  • Registratie: Februari 2000
  • Laatst online: 25-04 06:43

Macros

I'm watching...

Mark platvoet, je methode loopt nu op Orde(N) waar N het aantal componenten is, terwijl de versie met de HashMap Orde(1) loopt. Ik weet, het maakt niet veel uit, maar het zal waarschijnlijk in je event dispatch thread lopen, en die wil je snel hebben, en niet langzaam. Door dit soort amateuristisch geprogrammeer heeft Java de reputatie behouden dat het traag zou zijn, en dat is het ook als je je hele programma zo programmeerd.

"Beauty is the ultimate defence against complexity." David Gelernter


Verwijderd

Macros schreef op zaterdag 05 november 2005 @ 16:29:
Door dit soort amateuristisch geprogrammeer heeft Java de reputatie behouden dat het traag zou zijn, en dat is het ook als je je hele programma zo programmeerd.
Euh, door dit soort amateuristisch oninteressant geoptimaliseer krijg je pruts code. Je moet met een Map nu een schaduw boekhouding gaan bijhouden enkel omdat je een platgeslagen lijst wil hebben. Dat levert domweg onhandelbare code aangezien je voor een simpele component creatie extra handelingen moet verrichten. Tevens mag je wel eens aantonen dat je code significant sneller is met zo'n schaduw boekhouding. Ik weet nu al dat het geen donder uitmaakt.

Optimaliseren doe je omdat je profiler aantoont dat een bepaald onderdeel retetraag is. Niet omdat je denkt dat het nodig is maar daat geen gegrond bewijs voor hebt.

  • Macros
  • Registratie: Februari 2000
  • Laatst online: 25-04 06:43

Macros

I'm watching...

Ja, mijn 'schaduw boekhouding' is zoveel complexer dan jouw extreem simpele overduidelijke recursieve functie waarbij je uitgaat dat elk component een name geset heeft. Oh, dat is geen schaduwboekhouding zeg je? Oh, ik vind anders van wel...

Mijn code telt 3 regels, 3 keer zoweinig als die van jou. Ik zijn geen enkel argument voor jouw code. Mijn code is niet alleen efficienter, het is simpeler, makkelijker te onderhouden. Maak maar een applicatie met veel geneste componenten, dan zal je het vanzelf zien. Als je je hele programma schrijft onder het motto, later optimaliseer ik wel, dan zal je merken dat je programma enorm traag wordt. Lastige optimalisaties moet je uitstellen en later bekijken met een profiler, maar dit soort dingen toch niet...

"Beauty is the ultimate defence against complexity." David Gelernter


Verwijderd

Macros schreef op zaterdag 05 november 2005 @ 20:03:
Ja, mijn 'schaduw boekhouding' is zoveel complexer dan jouw extreem simpele overduidelijke recursieve functie waarbij je uitgaat dat elk component een name geset heeft. Oh, dat is geen schaduwboekhouding zeg je? Oh, ik vind anders van wel..
Laten we de feiten even op een rijtje zetten:
Op dit moment staat er al een structuur, namelijk een boom van componenten. Dus jou map oplossing is daadwerkelijk een schaduw boekhouding aangezien je opeens twee lijsten beheert. Mutaties op de lijst moeten bij je "oplossing" twee keer worden uitgevoerd.

Met betrekking tot snelheids winst voegt je Map oplossen werkelijkwaar niets toe, ga het maar is eens testen. Dan zul je het zelf zien. Je levert dus domweg slechte code. :)

En nou kappen met je geneuzel.

[ Voor 4% gewijzigd door Verwijderd op 05-11-2005 20:12 ]


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 21:10

.oisyn

Moderator Devschuur®

Demotivational Speaker

Verwijderd schreef op zaterdag 05 november 2005 @ 16:59:
Euh, door dit soort amateuristisch oninteressant geoptimaliseer krijg je pruts code.
Amateuristisch? Prutscode? Je houdt er maar een rare mening op na. Macros' code is duidelijk, recht-door-zee en minder error-prone dan zelf een functie schrijven die een boomstructuur afzoekt. Daarnaast kost het simpelweg minder tijd om te implementeren. Ik ben het met je eens dat premature optimizations the root of all evil zijn, maar dit is gewoonweg geen premature optimization: Je wilt een associatie implementeren tussen een string en een control. Een hashtable of een map is daar de geschikte datastructuur voor.
En nou kappen met je geneuzel.
Doe eens even normaal.

[ Voor 28% gewijzigd door .oisyn op 05-11-2005 20:40 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Tyf
  • Registratie: December 2002
  • Laatst online: 28-11-2025
Ok ik merkt dat er hier een kleine ruzie is.
Mijn eerste idee was ook, er bestaat al een structuur waar alle objecten in zitten dus waarom het nog bijhouden in een 2de structuur. Ik had al een recursieve oplossing gevonden maar die werkte maar half.
Daarna ben heb ik het voorbeeldje van Macros geprobeerd en deze werkte direct zonder problemen.
Bij de recursieve versie had ik veel problemen met null value's van sommige objecten (geen idee waarom code leek op eerste zicht juist) en objecten waarvan ik het bestaan niet eens afwist (glasspane ofzo).
Ook vind ik (zoals eerder aangeven) dat de zoektijd bij de hashmap veeel korter is dan de recursieve manier. En alle beetjes helpen om een programma performanter te houden :) en het verbruikt nu niet echt veel meer geheugen (denk ik).
Conclusie is, ik moet nog meer leren van java en de simple manier was voor mij ook de beste manier. Ik dank nog eens iedereen voor zijn hulp. Nu ga ik me op het reflection probleem smijten.
Wat ik nu al van reflection gelezen heb is dat je een externe classe kan inladen @runtime. En deze klasse dan kan gebruiken in je programma. Hopelijk klopt dit. En is deze reflection wel de goede manier om mijn probleem (het inlezen van actions in xml) uit te voeren?

[ Voor 17% gewijzigd door Tyf op 05-11-2005 20:50 ]


Verwijderd

Geen ruzie, als mijn simpele voorbeeld waarin ik stel dat je het recursief KUNT implementeren wordt bestempeld als amateuristisch dan wordt ik dan moet ik daar uiteraard op reageren. Zeker als het een amateur betreft die de opmerking maakt.

  • Tyf
  • Registratie: December 2002
  • Laatst online: 28-11-2025
misschien nu iets off-topic omdat ik het probleem al anders opgelost heb, maar ik wel graag leer uit mijn fouten. Kan mark (of een andere vrijwillige ;) ) mij misschien vertellen waarom deze code zo'n problemen gaf? Waarschijnlijk een domme fout maar mijn ervaring met java is niet zo groot.

Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
    public JComponent zoekOpNaam(String naam, JFrame container) {
        JComponent jc = null;

        int i = 0;

        while ((i < container.getComponentCount()) && (jc == null)) {
            jc = rec_zoekopnaam(naam, (JComponent) container.getComponent(i));
        }
        return jc;
    }

    private JComponent rec_zoekopnaam(String naam, JComponent container) {
        JComponent result = null;

        if (container.getName().compareTo(naam) == 0)
            result = container;
        else {
            int i = 0;
            System.out.println("in else");
            while ((i < container.getComponentCount()) && (result == null)) {
                result = rec_zoekopnaam(naam, (JComponent) container.getComponent(i));
            }
        }

        return result;
    }


Ik doe het in 2 delen de recursieve manier omdat ik vertrek van een jframe en geen jComponent.

[ Voor 4% gewijzigd door Tyf op 05-11-2005 21:14 ]


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 21:10

.oisyn

Moderator Devschuur®

Demotivational Speaker

Je vergeet i op te hogen in beide loopjes, waar je imho sowieso beter een for had kunnen gebruiken :).
Overigens snap ik niet waarom je in zoekOpNaam ook een loopje hebt staan. Kun je niet beter gewoon je rec_zoekopnaam aanroepen met het startcomponent waar je het zoeken wilt beginnen?

[ Voor 50% gewijzigd door .oisyn op 05-11-2005 21:18 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Tyf
  • Registratie: December 2002
  • Laatst online: 28-11-2025
hehe domme fout die i :) maar dit was zelf het probleem nog niet. Zover ging hij niet. Hij gaf al een null exception bij de eerste loop. Dus waar de i nog niet verhoogt diende te worden.

Die 2de loop had misschien idd weg gemogen. Maar ik wou dat beide appart konden werken. Ofwel zoeken met als basis je frame, ofwel zoeken met als basis een component. Zodat ik de fucntie later voor iets anders misschien nog kon gebruiken.
Het startcomponent weet je niet. Het engiste wat je zeker bent is de frame. En daarom begin ik hiermee.

[ Voor 53% gewijzigd door Tyf op 05-11-2005 21:26 ]


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 21:10

.oisyn

Moderator Devschuur®

Demotivational Speaker

Ik ken Spring niet echt, maar JFrame implementeert neem ik aan ook iets een container interface? Dus de interface waar getComponentCount en getComponent in gedefinieerd zijn. Als je van die JComponent parameter in je rec_zoekopnaam naar dat type verandert, kun je je frame gewoon megeven aan die functie. En die nullpointerexception komt volgens mij simpelweg door het feit dat je functie wordt aangeroepen met null als JFrame.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Bluestorm
  • Registratie: Januari 2000
  • Laatst online: 20-08-2022
Wat ook goed kan is dat er componenten in je structuur zitten zonder naam. container.getName() is dan null en ga jij er lekker een compareTo op aanroepen. Maar dat soort dingen moet je zowieso wel simpel kunnen achterhalen met een debugger of gewoon wat variabelen printen.

En mark, als je bij de hashmap oplossing het uitvoeren van twee acties bezwaarlijk vind stop je het toch gewoon samen in één functie...

[ Voor 21% gewijzigd door Bluestorm op 05-11-2005 21:36 ]

Tenminste... dat [ denk / zie / weet ] ik... | Javascript obfuscator | foto's en video's uploaden


  • Nick_S
  • Registratie: Juni 2003
  • Laatst online: 22-04 03:55

Nick_S

++?????++ Out of Cheese Error

Als je zeker weet dat naam ongelijk is aan null, dan kun je beter
code:
1
naam.equals(container.getName())

doen. Dan voorkom je weer een kans op een nullpointerexception.

Ook geeft naam.equals al een boolean terug, dus hoef je niet meer te checken of de uitkomt gelijk is aan 0.

'Nae King! Nae quin! Nae Laird! Nae master! We willna' be fooled agin!'

Pagina: 1