NetBeans 6 final - Java Desktop App

Alles was zukünftige Version von NetBeans betrifft (Q-Builds, Beta, Milstone, Dev-Builds usw.)

Moderator: wegus

Antworten
Daniel_L
Beiträge: 304
Registriert: 06.12.2006, 14:58
Wohnort: Hamburg
Kontaktdaten:

NetBeans 6 final - Java Desktop App

Beitrag von Daniel_L » 11.05.2007, 19:31

Schwierig, das richtige Forum dafür zu finden, mal sehen, ob ich hier richtig bin.

Ich habe ein paar Fragen zu dem neuen Projekt "Java Desktop Application", das ja schon ein kleines, fertiges Miniprogramm basierend auf dem Swing App Framework erstellt.

Hier ein paar Dinge, die ich noch nicht ganz verstehe, wohl weil ich sowohl was Java aber auch Netbeans angeht noch Anfänger bin:

1.) taskmonitor / taskmonitorpropertychange
Im geschützten initmethod()-Bereich wird diese Eigenschaft erstellt/initiiert. Aber finde ich die auch irgendwo in Design-Ansicht von Matisse? Wie kann ich hier einen eigenen Taskmonitor erstellen und wozu bzw. muss ich das überhaupt?

2.) Die Task method (doNothing)
Startet der Taskmonitor jedes mal mit einem Task, der bspw. durch Buttonklick ausgelöst wird? Also: Klick auf Button oder Menüpunkt started den Taskmonitor?

3.) Event PropertyName
Wo werden diese definiert? Und woher weiß der Taskmonitor bzw. das TaskMonitorPropertyChangeEvent (bin ich dankbar, dass Matisse diese Wörter bereits von selbst erstellt ;-) ), welches Event ausgelöst wurde?

4.) der doInBackground Task
Ist diese generell vordefiniert, oder woher weiß das Programm, dass diese Methode asynchron läuft?


Etwas steig ich da ja schon durch, dass bspw. über den Property Inspector den jeweiligen Komponenten eine neue "Action" zugewiesen werden bzw. auch erstellt werden kann. Diese Angaben werden dann in der ResourceMap gespeichert und können dort auch nachträglich editiert werden. Aber so ganz steige ich noch nicht durch dieses "Template" Java Desk Application durch...
Zuletzt geändert von Daniel_L am 09.01.2008, 17:44, insgesamt 1-mal geändert.

Daniel_L
Beiträge: 304
Registriert: 06.12.2006, 14:58
Wohnort: Hamburg
Kontaktdaten:

NetBeans 6.0 final

Beitrag von Daniel_L » 09.01.2008, 17:08

So, ich stelle meine Frage noch mal, vielleicht hat ja schon der eine oder andere Erfahrungen gesammelt oder weiß mehr.

Wenn ich unter NB6 eine Java Desktop App als neues Projekt erstelle, erscheinen ja einige Vorgaben, wie bspw:

Code: Alles auswählen

        // status bar initialization - message timeout, idle icon and busy animation, etc
        ResourceMap resourceMap = getResourceMap();
        int messageTimeout = resourceMap.getInteger("StatusBar.messageTimeout");
        messageTimer = new Timer(messageTimeout, new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                statusMessageLabel.setText("");
            }
        });
        messageTimer.setRepeats(false);
        int busyAnimationRate = resourceMap.getInteger("StatusBar.busyAnimationRate");
        for (int i = 0; i < busyIcons.length; i++) {
            busyIcons[i] = resourceMap.getIcon("StatusBar.busyIcons[" + i + "]");
        }
        busyIconTimer = new Timer(busyAnimationRate, new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                busyIconIndex = (busyIconIndex + 1) % busyIcons.length;
                statusAnimationLabel.setIcon(busyIcons[busyIconIndex]);
            }
        });
        idleIcon = resourceMap.getIcon("StatusBar.idleIcon");
        statusAnimationLabel.setIcon(idleIcon);
        progressBar.setVisible(false);

        // connecting action tasks to status bar via TaskMonitor
        TaskMonitor taskMonitor = new TaskMonitor(getApplication().getContext());
        taskMonitor.addPropertyChangeListener(new java.beans.PropertyChangeListener() {
            public void propertyChange(java.beans.PropertyChangeEvent evt) {
                String propertyName = evt.getPropertyName();
                if ("started".equals(propertyName)) {
                    if (!busyIconTimer.isRunning()) {
                        statusAnimationLabel.setIcon(busyIcons[0]);
                        busyIconIndex = 0;
                        busyIconTimer.start();
                    }
                    progressBar.setVisible(true);
                    progressBar.setIndeterminate(true);
                } else if ("done".equals(propertyName)) {
                    busyIconTimer.stop();
                    statusAnimationLabel.setIcon(idleIcon);
                    progressBar.setVisible(false);
                    progressBar.setValue(0);
                } else if ("message".equals(propertyName)) {
                    String text = (String)(evt.getNewValue());
                    statusMessageLabel.setText((text == null) ? "" : text);
                    messageTimer.restart();
                } else if ("progress".equals(propertyName)) {
                    int value = (Integer)(evt.getNewValue());
                    progressBar.setVisible(true);
                    progressBar.setIndeterminate(false);
                    progressBar.setValue(value);
                }
            }
        });
    }
Wenn man sich das Beispiel "DocumentEditor" anschaut, ist der obige Code auch enthalten. Nun werden damit ja bestimmte Arbeitsabläufe, die eine Klasse so erledigt, als Task deklariert, bspw:

Code: Alles auswählen

    /**
     * Prompt the user for a filename and then attempt to load the file.
     * <p>
     * The file is loaded on a worker thread because we don't want to
     * block the EDT while the file system is accessed.  To do that,
     * this Action method returns a new LoadFileTask instance, if the
     * user confirms selection of a file.  The task is executed when
     * the "open" Action's actionPerformed method runs.  The
     * LoadFileTask is responsible for updating the GUI after it has
     * successfully completed loading the file.
     * 
     * @return a new LoadFileTask or null
     */
    @Action
    public Task open() {
        JFileChooser fc = createFileChooser("openFileChooser");
        int option = fc.showOpenDialog(getFrame());
        Task task = null;
        if (JFileChooser.APPROVE_OPTION == option) {
            task = new LoadFileTask(fc.getSelectedFile());
        }
        return task;
    }

    /**
     * A Task that loads the contents of a file into a String.  The
     * LoadFileTask constructor runs first, on the EDT, then the
     * #doInBackground methods runs on a background thread, and finally
     * a completion method like #succeeded or #failed runs on the EDT.
     * 
     * The resources for this class, like the message format strings are 
     * loaded from resources/LoadFileTask.properties.
     */
    private class LoadFileTask extends DocumentEditorApp.LoadTextFileTask {
        /* Construct the LoadFileTask object.  The constructor
         * will run on the EDT, so we capture a reference to the 
         * File to be loaded here.  To keep things simple, the 
         * resources for this Task are specified to be in the same 
         * ResourceMap as the DocumentEditorView class's resources.
         * They're defined in resources/DocumentEditorView.properties.
         */
        LoadFileTask(File file) {
            super(DocumentEditorView.this.getApplication(), file);
        }

        /* Called on the EDT if doInBackground completes without 
         * error and this Task isn't cancelled.  We update the
         * GUI as well as the file and modified properties here.
         */
        @Override protected void succeeded(String fileContents) {
            setFile(getFile());
            textArea.setText(fileContents);
            setModified(false);
        }

        /* Called on the EDT if doInBackground fails because
         * an uncaught exception is thrown.  We show an error
         * dialog here.  The dialog is configured with resources
         * loaded from this Tasks's ResourceMap.
         */
        @Override protected void failed(Throwable e) {
            logger.log(Level.WARNING, "couldn't load " + getFile(), e);
            String msg = getResourceMap().getString("loadFailedMessage", getFile());
            String title = getResourceMap().getString("loadFailedTitle");
            int type = JOptionPane.ERROR_MESSAGE;
            JOptionPane.showMessageDialog(getFrame(), msg, title, type);
        }
    }
So ganz versteh ich das Prinzip noch nicht. Was bedeutet dieser TaskMonitor genau, und wie könnte ich dort eigene Aufgaben/Methoden/Funktionen einbinden, die im Hintergrund, also asynchron verlaufen sollen? Und wie kann ich hier dabei den Statusbar-Text beeinflussen? Hat sich damit schon mal jemand näher auseinandergesetzt, oder gibt es dazu tutorials?

Daniel_L
Beiträge: 304
Registriert: 06.12.2006, 14:58
Wohnort: Hamburg
Kontaktdaten:

Beitrag von Daniel_L » 09.01.2008, 17:52

Also, ein erster Ansatzpunkt wäre das dazugehörige AppFramework JavaDoc, aber als Java-Anfänger ist das doch recht mühsam, da durchzusteigen.

Bin also über weitere Tipps, Hinweise und Antworten dankbar! :-)

Daniel_L
Beiträge: 304
Registriert: 06.12.2006, 14:58
Wohnort: Hamburg
Kontaktdaten:

Beitrag von Daniel_L » 16.01.2008, 16:51

So, ich versuch das nochmal zusammenzufassen, mal sehen, ob ich alles verstanden habe. Falls ich irgendwo falsch liege und es jemandem auffällt, bitte korrigieren!

Code: Alles auswählen

        messageTimer = new Timer(messageTimeout, new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                statusMessageLabel.setText("");
            }
        }); 
Hier wird ein Timer erstellt, der - wenn aktiv - im Hintergrund läuft und nach messageTimeout Sekunden den Text der Statusbar löscht (weil dies im actionPerformed event so aufgerufen wird, also dann, wenn der Timer abgelaufen ist). Wiederholt sich nicht, da mit setRepeats(false) Wiederholung ausgeschaltet wurde.



Code: Alles auswählen

        int busyAnimationRate = resourceMap.getInteger("StatusBar.busyAnimationRate");
        for (int i = 0; i < busyIcons.length; i++) {
            busyIcons[i] = resourceMap.getIcon("StatusBar.busyIcons[" + i + "]");
        }
        busyIconTimer = new Timer(busyAnimationRate, new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                busyIconIndex = (busyIconIndex + 1) % busyIcons.length;
                statusAnimationLabel.setIcon(busyIcons[busyIconIndex]);
            }
        }); 
Ein weiterer Timer, der jedesmal, wenn ausgelöst nach busyAnimateRate Sekunden, aus einem Icon-Array das nächste Icon ausliest und in einen Label setzt. Ist sozusagen eine Dauer-Animation, die im Hintergrund läuft, wenn sie gestartet wurde.

Code: Alles auswählen

        TaskMonitor taskMonitor = new TaskMonitor(getApplication().getContext());
        taskMonitor.addPropertyChangeListener(new java.beans.PropertyChangeListener() {
            public void propertyChange(java.beans.PropertyChangeEvent evt) {
                String propertyName = evt.getPropertyName(); 
Ein TaskMonitor, dessen Aufgabe es ist, gestartete Tasks zu beobachten. Offensichtlich sendet jeder Task bestimmte Nachrichten:
- started
- done
- message
- progress
Dies passiert automatisch, darum braucht/kann man sich nicht kümmern.
Das, was jetzt folgt, wird von jedem Task durchgeführt, egal welche Funktion/Action ihn startet:

Code: Alles auswählen

                String propertyName = evt.getPropertyName();
                if ("started".equals(propertyName)) {
                    if (!busyIconTimer.isRunning()) {
                        statusAnimationLabel.setIcon(busyIcons[0]);
                        busyIconIndex = 0;
                        busyIconTimer.start();
                    }
                    progressBar.setVisible(true);
                    progressBar.setIndeterminate(true);
                } else if ("done".equals(propertyName)) {
                    busyIconTimer.stop();
                    statusAnimationLabel.setIcon(idleIcon);
                    progressBar.setVisible(false);
                    progressBar.setValue(0);
                } else if ("message".equals(propertyName)) {
                    String text = (String)(evt.getNewValue());
                    statusMessageLabel.setText((text == null) ? "" : text);
                    messageTimer.restart();
                } else if ("progress".equals(propertyName)) {
                    int value = (Integer)(evt.getNewValue());
                    progressBar.setVisible(true);
                    progressBar.setIndeterminate(false);
                    progressBar.setValue(value);
                }
            } 

Kann es aber sein, dass im DocumentEditor-Sample (siehe Posting oben) niemals ein backGround-Task gestartet wird? Ich zitiere noch mal den Kommentar:

Code: Alles auswählen

    /**
     * A Task that loads the contents of a file into a String.  The
     * LoadFileTask constructor runs first, on the EDT, then the
     * #doInBackground methods runs on a background thread, and finally
     * a completion method like #succeeded or #failed runs on the EDT.
     *
     * The resources for this class, like the message format strings are
     * loaded from resources/LoadFileTask.properties.
     */ 

Aber wenn ich mir die folgende Methode/Funktion angucke, passiert gar nichts in Bezug auf backGround-Tasks (vll. ein Überbleibsel der vorigen NB6-Versionen?)

Hab ich soweit alles richtig verstanden?

NetworkerDeluxe
Beiträge: 1
Registriert: 11.01.2009, 08:53

Beitrag von NetworkerDeluxe » 11.01.2009, 09:00

Schaut mal hier nach, dort ist das Framework erklärt und hier sind einige Beispiele wie man es einsetzt:

https://appframework.dev.java.net/

und hier

https://appframework.dev.java.net/intro/index.html

Hat ja nur ein Jahr gedauert bis das jemand mal erweitert hat. Super Leistung!

Munter...

Daniel_L
Beiträge: 304
Registriert: 06.12.2006, 14:58
Wohnort: Hamburg
Kontaktdaten:

Beitrag von Daniel_L » 12.01.2009, 06:04

Danke für die Antwort. Mittlerweile habe ich mich recht gut (für meine Verhältnisse) eingearbeitet und verstehe auch, wie das mit den Backgroundtasks etc. funktioniert.

Antworten