[Java] Generieke Wizard opzetten

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • Matis
  • Registratie: Januari 2007
  • Laatst online: 11-09 20:27

Matis

Rubber Rocket

Topicstarter
Beste PRGers,

Momenteel ben ik een inhouse-tool aan het maken waarmee we een statusfile (theorie) tegen een stukje software (praktijk) willen testen. Even wat voorkennis; In de statusfile staan een aantal zaken. Zoals het hardwareplatform waarop de software moet komen te draaien. Het versienummer van de software, wie er verantwoordelijk is voor de vrijgave, de bestandsnaam van de software en (eventueel) welke extra configuratiebestanden er bij moeten zitten.
De flowdiagram ziet er (globaal) zo uit:
  • Gebruiker verricht handelingen op JPanel
  • Gebruiker klikt op volgende
  • Software voert check uit ? Ga naar de volgende JPanel : Toon waarschuwing en blijf op JPanel
  • Ga naar stap 1
Zo komen er meer schermen achter elkaar welke in chronologische volgorde doorlopen moet worden.
Ik ben al een beetje aan het rommelen geweest, maar kom niet tot een generieke opzet. Ik krijg de relaties tussen de benodigde klassen niet voor elkaar.

Wat ik momenteel heb is het volgende:
  • MainWindow extends JFrame (BorderLayout)
    • CENTER: Panel1 extends WizardPanel
    • SOUTH: MenuBar extends JPanel (Hierin staan de cancel, vorige, volgende en finish knoppen met bijbehorende ActionListners)
  • abstract WizardPanel extends JPanel
    • public abstract boolean nextPage();
    • public abstract boolean prevPage();
    • public abstract boolean cancel();
    • public abstract boolean Finish();
Nu moet er waarschijnlijk nog een klasse bijkomen welke de administratie regelt.
Echter krijg ik het niet voor elkaar om middels een extends of implements meerdere JPanels "achter elkaar te knopen". Ook lukt het me niet om voor de active JPanel, de juiste next() (met daarin de checks) uit te voeren.

Hebben jullie tips hoe dit te implementeren?

Alvast bedankt _O_

Matis

If money talks then I'm a mime
If time is money then I'm out of time


Acties:
  • 0 Henk 'm!

  • Herko_ter_Horst
  • Registratie: November 2002
  • Niet online
http://java.sun.com/devel...rticles/GUI/swing/wizard/

[ Voor 81% gewijzigd door Herko_ter_Horst op 21-06-2012 13:23 ]

"Any sufficiently advanced technology is indistinguishable from magic."


Acties:
  • 0 Henk 'm!

  • Ethnocentrix
  • Registratie: Augustus 2002
  • Laatst online: 12-09 10:29

Ethnocentrix

Rijkserkend prutser

Ik heb het zelf zo wel eens ongeveer opgelost:

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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
abstract class WizardPanel extends JPanel {
    private WizardPanel previousPanel = null;
    private WizardPanel nextPanel = new WizardPanelTwo();   
    
    /**
     * Valideert de invulvelden in het panel.
     */
    abstract boolean validatePanel();

    /**
     * Geeft het volgende Wizard scherm terug.
     */
    abstract WizardPanel getNextPanel();
    
    public WizardPanel getPreviousPanel() {
        return previousPanel;
    }
    
    public WizardPanel getNextPanel() {
        return nextPanel;
    }
}

class WizardPanelOne extends WizardPanel {
    // scherm 1
}

class WizardPanelTwo extends WizardPanel {
    // scherm 2
}

class Wizard extends JPanel {
    private WizardPanel currentPanel = new WizardPanelOne();
    
    public Wizard() {
        // ...
    }
    
    public boolean requestSwitchToPanel(final WizardPanel panel) {
        if (!currentPanel.validatePanel())
        {
            return false;
        }
        
        if (panel.getPreviousPanel() == null) {
            // disable previous button
        }
        
        if (panel.getNextPanel() == null) {
            // disable next button
        }
        
        panel.setPreviousPanel(currentPanel);
        currentPanel = panel;

        SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                        add(panel, BorderLayout.CENTER);        
                }
        });
        
        return true;
    }
}


Elke stap in je wizard weet wat zijn volgende stap is.(of bepaald dit adhv de keuzes van de gebruiker in dat scherm). Zodra er op de knop 'next' geklikt wordt vraagt je Wizard aan het scherm zichzelf te valideren. Als dat goed gaat vraag je het volgende scherm (dit zou je natuurlijk ook kunnen combineren).

[ Voor 5% gewijzigd door Ethnocentrix op 21-06-2012 14:04 ]

You know you're an engineer if you have no life & can prove it mathematically.


Acties:
  • 0 Henk 'm!

  • Herko_ter_Horst
  • Registratie: November 2002
  • Niet online
Er zijn overigens ook nog wel wat open source Swing Wizard frameworks te vinden met een beetje Googlen. Hier staan er een aantal: http://stackoverflow.com/...end-a-java-wizard-library

[ Voor 32% gewijzigd door Herko_ter_Horst op 21-06-2012 15:04 ]

"Any sufficiently advanced technology is indistinguishable from magic."


Acties:
  • 0 Henk 'm!

  • Matis
  • Registratie: Januari 2007
  • Laatst online: 11-09 20:27

Matis

Rubber Rocket

Topicstarter
Bedankt allemaal voor de berichten. Ik ga het voorstel van Ethnocentrix in "[Java] Generieke Wizard opzetten" verder uitwerken, omdat ik dat het beste kan doorgronden.

If money talks then I'm a mime
If time is money then I'm out of time


Acties:
  • 0 Henk 'm!

  • Matis
  • Registratie: Januari 2007
  • Laatst online: 11-09 20:27

Matis

Rubber Rocket

Topicstarter
Edit2; Ik heb de oplossing gevonden: Zie onderaan!

Ik ben vandaag verder gegaan met het ontwikkelen van mijn Wizard.

De ontwikkelingen gaan voorspoedig en ik baseer me nog steeds op het gegeven van Ethnocentrix in "[Java] Generieke Wizard opzetten" . Nu loop ik alleen tegen een probleempje van Java / Swing aan.

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
public boolean requestSwitchToPanel(final WizardPanel panel, final Direction direction)
    {
        /* When we initialize or navigate backwards, there is no need for checking */
        if ((direction == Direction.FORWARD) && (_currentPanel.validatePanel() == false))
        {
            return false;
        }
        if(direction == Direction.FORWARD)
        {
            panel.setPreviousPanel(_currentPanel);
        }
        _btnBack.setEnabled((panel.getPreviousPanel() == null) ? false : true);
        _btnNext.setEnabled((panel.getNextPanel() == null) ? false : true);
        SwingUtilities.invokeLater(new Runnable()
        {
            public void run()
            {
                remove(_currentPanel);
                add(panel, BorderLayout.CENTER);
                revalidate();
            }
        });
        _currentPanel = panel;
        return true;
    }

Op de "heenweg" worden netjes alle panels gevuld en geüpdatet. Ik krijg One Two Three te zien in de JLabels van iedere panel. Wanneer ik echter "terugga" door de Wizard, blijft helaas de laatste (Three) JLabel zichtbaar. Echter reageren de buttons wel goed. Ze worden enabled/disabled wanneer ze moeten en ook in de debugger zie ik netjes de juiste panels voorbij komen in de add()-functie.
Ik heb een button toegevoegd welke de _currentPanel.toString() laat zien. Deze toont ook netjes de verwachtte JPanel klassenaam.
Overigens maak het daarna ook niet meer uit of ik heen of terug ga, alleen de laatste JPanel (Three) blijft zichtbaar binnen het frame.

Wie weet waarom?

Edit; Er zit/zat een klein probleempje met threading en het asynchroon aanroepen van de invokeLater. Daardoor werd de _currentPanel voortijdig al overschreven.
Dit heb ik nu aangepast en tevens logging toegevoegd; Zo ziet de code er nu uit:
Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
SwingUtilities.invokeLater(new Runnable()
        {
            public void run()
            {
                if (_currentPanel != null)
                {
                    System.out.printf("Removing %s\n", _currentPanel.getClass().getName());
                    remove(_currentPanel);
                }
                System.out.printf("Adding %s\n", panel.getClass().getName());
                add(panel, BorderLayout.CENTER);
                _currentPanel = panel;
                validate();
            }
        });

En dit is de uitvoer van de console; Let wel: Ik ga een keer heen en een keer terug.
Adding com.matis_digital.test.PanelOne
Removing com.matis_digital.test.PanelOne
Adding com.matis_digital.test.PanelTwo
Removing com.matis_digital.test.PanelTwo
Adding com.matis_digital.test.PanelThree
Removing com.matis_digital.test.PanelThree
Adding com.matis_digital.test.PanelTwo
Removing com.matis_digital.test.PanelTwo
Adding com.matis_digital.test.PanelOne


Edit2; Waarom het op de heenweg wel goed en op de terugweg niet is me een raadsel. Maar ik heb nu de volgende code; welke precies doet wat ik wil :)
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
public boolean requestSwitchToPanel(final WizardPanel panel, final Direction direction)
    {
        /*
         * When we initialize or navigate backwards, there is no need for
         * checking.
         */
        if ((direction == Direction.FORWARD) && (_currentPanel.validatePanel() == false))
        {
            return false;
        }
        if (direction == Direction.FORWARD)
        {
            panel.setPreviousPanel(_currentPanel);
        }
        _btnBack.setEnabled((panel.getPreviousPanel() == null) ? false : true);
        _btnNext.setEnabled((panel.getNextPanel() == null) ? false : true);
        SwingUtilities.invokeLater(new Runnable()
        {
            public void run()
            {
                if (_currentPanel != null)
                {
                    System.out.printf("Removing %s\n", _currentPanel.getClass().getName());
                    remove(_currentPanel);
                }
                System.out.printf("Adding %s\n", panel.getClass().getName());
                add(BorderLayout.CENTER, panel);
                revalidate();
                repaint();
                _currentPanel = panel;
            }
        });
        return true;
    }

Het probleem zit heb dus in de repaint. Dat ik die niet aanriep.

[ Voor 43% gewijzigd door Matis op 24-06-2012 20:28 ]

If money talks then I'm a mime
If time is money then I'm out of time

Pagina: 1