2016-10-12 6 views
1

Dieses JFrame das erste Mal, wenn ich es rufe, wenn die Anwendung läuft, funktioniert perfekt. Aber wenn ich versuche, eine neue Datei zu öffnen, soll der Fortschrittsbalken zum Bildschirm zurückkehren. Sehen Sie sich die Screenshots an, um zu sehen, wie es danach aussehen soll.JFrame erscheint nach dem ersten Aufruf leer

public ArrayList<Data> handleData(File fileToOpen) throws FileNotFoundException { 
     ArrayList<Data> handle = new ArrayList<Data>(); 
    //clear the arraylist the second time round 
    handle.clear(); 

    BufferedReader reader = new BufferedReader(new FileReader(fileToOpen)); 
    //buffer used for scanner 
    int lines = 0; 
    //find out the value of lines here 

    JFrame loader = new JFrame(); 
    JPanel loadPanel = new JPanel(); 
    JProgressBar progressBar = new JProgressBar(0, lines); 
    JLabel label = new JLabel(); 

    loader.setDefaultCloseOperation(EXIT_ON_CLOSE); 
    label.setText("Loading Data..."); 
    loadPanel.add(label); 
    loadPanel.add(progressBar); 
    loader.add(loadPanel); 
    loader.pack(); 
    loader.setVisible(true); 

    //Do a load of stuff which increments the progress bar 
    loader.setVisible(false); 

    return handle; 
} 

Dies ist, wie die Fortschrittsbalken und JFrame aussehen sollten:

This is how the progress bar and JFrame should look.

Dies ist, wie die Fortschrittsbalken zum zweiten Mal sehen:

This Is how the progress bar looks the second time

Alle Code:

package Default; 

import java.awt.event.WindowEvent; 
import java.io.BufferedReader; 
import java.io.File; 
import java.io.FileNotFoundException; 
import java.io.FileReader; 
import java.io.IOException; 
import java.util.ArrayList; 
import java.util.Scanner; 

import javax.swing.JDialog; 
import javax.swing.JFileChooser; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JPanel; 
import javax.swing.JProgressBar; 
import javax.swing.SwingUtilities; 

@SuppressWarnings("serial") 
public class ReadIn extends JFrame { 

public File openFile() { 

    File fileToOpen = null; 

    JFileChooser fileChooser = new JFileChooser(); 
    int modalToComponent = fileChooser.showOpenDialog(this); 
    if (modalToComponent == JFileChooser.APPROVE_OPTION) { 
     fileToOpen = fileChooser.getSelectedFile(); 
    } else if (modalToComponent == JFileChooser.CANCEL_OPTION) { 
     System.exit(1); 
    } 

    return fileToOpen; 

} 

public ArrayList<Data> handleData(File fileToOpen) throws FileNotFoundException { 
    ArrayList<Data> handle = new ArrayList<Data>(); 
    handle.clear(); 

    BufferedReader reader = new BufferedReader(new FileReader(fileToOpen)); 

    int lines = 0; 

    try { 
     while (reader.readLine() != null) 
      lines++; 
     reader.close(); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 

    Scanner sc = new Scanner(fileToOpen); 

    System.out.println(sc.nextLine()); 
    System.out.println(sc.nextLine()); 
    System.out.println("Reading Data..."); 

    sc.nextLine(); 

    String split = sc.nextLine(); 
    Scanner splitter = new Scanner(split); 

    JDialog loader = new JDialog(); 
    JPanel loadPanel = new JPanel(); 
    JProgressBar progressBar = new JProgressBar(0, lines); 
    JLabel label = new JLabel(); 

    loader.setDefaultCloseOperation(HIDE_ON_CLOSE); 
    label.setText("Loading Data..."); 
    loadPanel.add(label); 
    loadPanel.add(progressBar); 
    loader.add(loadPanel); 
    loader.pack(); 
    loader.setVisible(true); 

    while (splitter.hasNext()) { 

     String peek = splitter.next(); 
     if (peek.equals("Timestamp")) { 
      peek = peek + splitter.next(); 
     } 
     Data temp = new Data(); 
     temp.setHeading(peek); 
     handle.add(temp); 

    } 

    while (sc.hasNextDouble()) { 
     progressBar.setValue(progressBar.getValue() + 1); 
     for (int i = 0; i < handle.size(); i++) { 
      handle.get(i).getValues().add(sc.nextDouble()); 

     } 

    } 
    System.out.println("Data Loaded"); 
    splitter.close(); 
    sc.close(); 
    loader.setVisible(false); 
    System.out.println("On EDT?: " + SwingUtilities.isEventDispatchThread()); 
    return handle; 
} 

}

Antwort

2

Ohne Ihre eine gültige minimal example program zu veröffentlichen, ist es für uns unmöglich, mit absoluter Sicherheit die Ursache des Problems zu wissen, schlägt das Bild, dass es ein Swing-Threading-Problem ist, dass Sie Code läuft Lang haben, wahrscheinlich hier:

blockiert den Swing-Ereignis-Thread, und das verursacht die Swing-GUI nicht selbst zu zeichnen.

Wenn dies der Fall ist, besteht die Lösung darin, Ihren Code so zu verbessern, dass er den Swing-Ereignisthread berücksichtigt, sodass lang laufender Code in einem Hintergrundthread wie einem SwingWorker ausgeführt wird.

Andere Probleme: das angezeigte Fenster scheint ein "abhängiges" Fenster und kein Hauptanwendungsfenster zu sein. Wenn dies der Fall ist, sollte es nicht als JFrame erstellt werden, sondern als JDialog, entweder modal oder nicht-modal, je nach Ihren Anforderungen.

Auch - warum funktioniert es das erste Mal? Wahrscheinlich wird der obige Code nicht beim Swing Event-Thread, dem EDT, ausgeführt, während er beim zweiten Aufruf dieses Codes tatsächlich auf dem EDT ausgeführt wird. Sie können dies testen, indem Sie SwingUtilities.isEventDispatchThread() aufrufen und das Ergebnis ausdrucken. z.B.

System.out.println("On EDT?: " + SwingUtilities.isEventDispatchThread()); 

Zum Beispiel:

import java.awt.BorderLayout; 
import java.awt.Dialog.ModalityType; 
import java.awt.Dimension; 
import java.awt.Window; 
import java.awt.event.ActionEvent; 
import java.awt.event.KeyEvent; 
import java.beans.PropertyChangeEvent; 
import java.beans.PropertyChangeListener; 
import java.io.File; 
import java.util.ArrayList; 
import java.util.concurrent.ExecutionException; 
import javax.swing.*; 

public class UpdateDataEg extends JPanel { 
    protected static final int MAX_LINES = 200; 

    public UpdateDataEg() { 
     setPreferredSize(new Dimension(500, 400)); 
     add(new JButton(new UpdateDataAction("Update Data", KeyEvent.VK_U))); 
    } 

    // this must be a void method as you'll get the result from a callback, not 
    // from this method 
    public void handleData(final File fileToOpen) { 
     int lines = 0; 
     // find out the value of lines here 

     Window window = SwingUtilities.getWindowAncestor(UpdateDataEg.this); 
     JDialog loader = new JDialog(window, "Progress", ModalityType.APPLICATION_MODAL); 
     JPanel loadPanel = new JPanel(new BorderLayout()); 
     final JProgressBar progressBar = new JProgressBar(0, 100); 
     progressBar.setStringPainted(true); 
     JLabel label = new JLabel(); 

     label.setText("Loading Data..."); 
     loadPanel.add(label, BorderLayout.PAGE_START); 
     loadPanel.add(progressBar); 
     loader.add(loadPanel); 
     loader.pack(); 
     loader.setLocationRelativeTo(window); 

     final SwingWorker<ArrayList<Data>, Void> myWorker = new SwingWorker<ArrayList<Data>, Void>() { 

      @Override 
      protected ArrayList<Data> doInBackground() throws Exception { 
       ArrayList<Data> handle = new ArrayList<Data>(); 
       // clear the arraylist the second time round 
       handle.clear(); 

       int lines = 0; 
       // !! BufferedReader reader = new BufferedReader(new FileReader(fileToOpen)); 

       // !! long code here to do calculations and place into ArrayList<Data> 
       // emulated by Thread.sleep 
       // !! set progress property here so that listener can update 
       while (lines < MAX_LINES) { 
        lines += (int) (10 * Math.random()); 
        int myProgress = (int) ((lines * 100)/MAX_LINES); 
        myProgress = Math.min(100, myProgress); 
        setProgress(myProgress); 
        Thread.sleep(200); 
       } 

       return handle; 
      } 

     }; 

     // our callback 
     myWorker.addPropertyChangeListener(new PropertyChangeListener() { 

      @Override 
      public void propertyChange(PropertyChangeEvent pcEvt) { 
       if (pcEvt.getPropertyName().equals("progress")) { 
        int progress = myWorker.getProgress(); 
        progressBar.setValue(progress); 
       } else if (pcEvt.getNewValue() == SwingWorker.StateValue.DONE) { 
        // if the worker has finished 
        loader.setVisible(false); 

        try { 
         ArrayList<Data> data = myWorker.get(); 
         // use data here 
        } catch (InterruptedException | ExecutionException e) { 
         // TODO handle the exceptions 
         e.printStackTrace(); 
        } 
       } 
      } 
     }); 

     myWorker.execute(); 
     // if the dialog is modal, this must be last 
     loader.setVisible(true); 

     // delete this call as this would be done from the callback 
     // loader.setVisible(false); 

     // delete this as this is obtained in the callback 
     // return handle; 
    } 

    private class UpdateDataAction extends AbstractAction { 
     public UpdateDataAction(String name, int mnemonic) { 
      super(name); 
      putValue(MNEMONIC_KEY, mnemonic); 
     } 

     @Override 
     public void actionPerformed(ActionEvent e) { 
      handleData(new File("Foobar.txt")); 
     } 
    } 

    private static void createAndShowGui() { 
     UpdateDataEg mainPanel = new UpdateDataEg(); 

     JFrame frame = new JFrame("UpdateDataEg"); 
     frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); 
     frame.getContentPane().add(mainPanel); 
     frame.pack(); 
     frame.setLocationByPlatform(true); 
     frame.setVisible(true); 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 
      public void run() { 
       createAndShowGui(); 
      } 
     }); 
    } 
} 

class Data { 

} 
+0

Das erste Mal, wenn die Systemausgaben "false". Das zweite Mal produziert es "wahr". – RMRiver

+0

@RMRiver: also hatte ich recht! das erste Mal, wenn Sie es anrufen, ist es aus dem EDT und das zweite Mal ist es auf dem EDT. :) –

+0

Ich liebe es wenn ich richtig rate. –

Verwandte Themen