JDialog Ladebildschirm wird nicht angezeit

daniel_sun

Erfahrenes Mitglied
Hallo,

ich habe mir einen kleinen Ladebildschirm gebastelt, da mein Programm an einer Stelle Datenbankoperationen ausführt, die zum teil bis zu 20 sek dauer.

Mein Bildschrim:

Code:
import java.awt.*;
 
import javax.swing.*;
 
public class DataFormSplashScreen extends JDialog{
 
        private JLabel actionLabel = new JLabel("[Aktion]");
        private JLabel detailLabel = new JLabel("[Detail]");
        private JProgressBar progress = new JProgressBar(0,10000);
        private JPanel panel;
 
        Font labelFont = new Font(this.getName(),Font.PLAIN,12);
        
        public DataFormSplashScreen(MovieDataForm owner){
            super(owner);
            this.setSize(400, 100);
            this.setLocationRelativeTo(null);
            this.setResizable(false);
            this.setUndecorated(true);
            this.setAlwaysOnTop(true);
            
            panel = new JPanel(null);
            panel.setBorder(BorderFactory.createLineBorder(Color.black));
           
            actionLabel.setSize(400, 15);
            actionLabel.setLocation(10,10);
            actionLabel.setFont(labelFont);
           
            detailLabel.setSize(400, 15);
            detailLabel.setLocation(10,30);
            detailLabel.setFont(labelFont);
            
            progress.setSize(380, 15);
            progress.setLocation(10,65);
           
            
            panel.add(actionLabel);
            panel.add(detailLabel);
            panel.add(progress);
               
            this.add(panel);
              
        }
        
        public void setProgressBarMaximum( int i){
            progress.setMaximum(i);
        }
    
        public void setActionLabel(String s){
            actionLabel.setText(s);
        }
        
        public void setDetailLabel(String s){
            detailLabel.setText(s);
        }
    
        public void setProgressBar(int i){
            progress.setValue(i);
        }
        
        public int getProgressBar(){
            return progress.getValue();
        }
}


Hier die Stelle in meiner DataForm.java wo der Splashscreen angezeigt wird(erzeugt wird das Objekt als Klassenvariable)

Code:
    public void insertData(){
        
        this.setEnabled(false);
        splashScreen.setVisible(true);
        
        int steps = picture.length + countryTable.getModel().getRowCount() + categoryTable.getModel().getRowCount()+ studioTable.getModel().getRowCount() + castTable.getModel().getRowCount();
        
        splashScreen.setProgressBarMaximum(steps);
        
 
        insertCast();
        insertStudio();
        insertCategory();
        insertCountry();
        insertPicture();
        insertMovie();
        
        owner.tree.addItem(locationCombo.getSelectedItem().toString(), titleField.getText());
        owner.tree.repaint();
        owner.tree.revalidate();
        
 
        closeWindow();
    }

in den 6 Methoden insertCast(); insertStudio(); insertCategory(); insertCountry(); insertPicture(); insertMovie(); werden die Datenbankoperationen ausgeführt. Dort wird nur der Value der ProgressBar und die Texte der beiden Label mittels der Setter verändert.

Das komische ist nun, kommentiere ich die Methoden der DBOperatioen aus wird der Labebildschirm angezeigt. Mit den Methoden (egal ob alle oder nur irgend eine) werden zwar die DB-Operationen ausgeführt, der Lade-Bildschirm aber nicht angezeit.

Prüfe ich die Sichtbarkeit mit splashScreen.isVisible() bekomme ich true zurück. Hab erst gedacht das er hinter dem Formular das ihn aufruft verschwindet, aber so scheint es nicht zu sein.

Bin mit meinem Latain am ende.

Gruß
Cromm Cruach

EDIT:

So habe noch ein wenig debugt. Hier noch mal der Code:

Code:
    public void insertData(){
        
        splashScreen = new DataFormSplashScreen();
        
                splashScreen.setVisible(true);
        this.setEnabled(false);
        
        int steps = picture.length + countryTable.getModel().getRowCount() + categoryTable.getModel().getRowCount()+ studioTable.getModel().getRowCount() + castTable.getModel().getRowCount();
        
        splashScreen.setProgressBarMaximum(steps);
        splashScreen.repaint();
        splashScreen.revalidate();
 
        //insertCast();
        //insertStudio();
        //insertCategory();
        //insertCountry();
        //insertPicture();
        //insertMovie();
        
        owner.tree.addItem(locationCombo.getSelectedItem().toString(), titleField.getText());
        owner.tree.repaint();
        owner.tree.revalidate();
        
        //splashScreen.dispose();
        //closeWindow();
    }


So wir der Screen angezeigt. Habe mal an jeder Zeile nen Breakpoint gesetzt. Der screen wird nicht am Punkt splashScreen.setVisible(true); angezeigt sondern erst am ende nach der Methode.

Kommentiere ich nur die letzten beiden Zeilen aus werden die Daten in die DB eingetragen und dann der Ladebildschirm angezeigt. Er ist dann korrekt "ausgefüllt" so wie es auch zu laufzeit geschehen soll. Er wird nur nicht angezeigt bzw zu spät!
 
Habe das Problem selber lösen können. Hinterlasse mal eine Nachricht, falls jemand nochmal auf das Problem stößt.

Problem: Das Problem ist, das mein Datenbankprozess so rechenintensiv war, dass er die GUI blockierte. Somit waren keine ressourcen mehr da, um den Screen anzuzeigen oder zu aktualisieren. Das passierte erst nachdem die DB-Operation erledigt und somit Rechenkapazität wieder frei war.

Lösung: Seit Java 6 gibt es einen sog. SwingWorker. Mit ihm kann man die Operation ( nicht die GUI) in einen neuen Thread auslagern. Im Formular legt man nur den Ladebildschirm an und startet den SwingWorker. In ihm finden die DB-Operationen statt und von ihm aus kann man auch den Ladebildschirm aktualisieren.
 
Zurück