2012-12-06 11 views
10

Die Anwendung verschlüsselt jede Datei, die in die Tabelle eingefügt wird, wenn Sie auf Verschlüsseln klicken, und ich möchte den Fortschritt der Dateien anzeigen, wie sie verschlüsselt werden. Die Spalte "Status" wechselt dann von "Nicht verarbeitet" zu "Verarbeitet".Hinzufügen von Fortschrittsbalken zu jeder Tabellenzelle für Dateifortschritt - Java

Ähnlich wie Sie mehrere Dateien in einer E-Mail anhängen. Ich habe den CellRenderer und die ProgressBarTableCell untersucht, bin mir aber nicht sicher, wie ich sie implementieren soll. Jede Hilfe wird geschätzt. Ich poste den Tisch.

 import java.awt.BorderLayout; 
    import java.awt.Color; 
    import java.awt.Dimension; 
    import java.awt.EventQueue; 
    import java.awt.Point; 
    import java.awt.datatransfer.DataFlavor; 
    import java.awt.datatransfer.Transferable; 
    import java.awt.datatransfer.UnsupportedFlavorException; 
    import java.awt.dnd.DnDConstants; 
    import java.awt.dnd.DropTarget; 
    import java.awt.dnd.DropTargetDragEvent; 
    import java.awt.dnd.DropTargetDropEvent; 
    import java.io.File; 
    import java.io.IOException; 
    import java.util.List; 

    import javax.swing.JFrame; 
    import javax.swing.JPanel; 
    import javax.swing.JScrollPane; 
    import javax.swing.JTable; 
    import javax.swing.UIManager; 
    import javax.swing.UnsupportedLookAndFeelException; 
    import javax.swing.table.DefaultTableModel; 

    public class DropTable { 

     public static void main(String[] args) { 
      new DropTable(); 
     } 

     public DropTable() { 
      EventQueue.invokeLater(new Runnable() { 
       @Override 
       public void run() { 
        try { 
         UIManager.setLookAndFeel(UIManager 
           .getSystemLookAndFeelClassName());//get look and feel of whatever OS we're using 
        } catch (ClassNotFoundException | InstantiationException 
          | IllegalAccessException 
          | UnsupportedLookAndFeelException ex) { 
        } 

        JFrame frame = new JFrame(); 
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
        frame.setLayout(new BorderLayout()); 
        frame.add(new DropPane()); 
        frame.pack(); 
        frame.setLocationRelativeTo(null); 
        frame.setVisible(true); 
       } 

      }); 
     } 

     public class DropPane extends JPanel { 

      /** 
      * 
      */ 
      private static final long serialVersionUID = 1L; 
      private JTable table; 
      private JScrollPane scroll; 
      private DefaultTableModel tm = new DefaultTableModel(new String[] { 
        "File", "File Type", "Size", "Status" }, 0); 

      public DropPane() { 
       table = new JTable(); 
       table.setShowGrid(true); 
       table.setShowHorizontalLines(true); 
       table.setShowVerticalLines(true); 
       table.setGridColor(Color.GRAY); 


       table.setModel(tm); 
       table.setFillsViewportHeight(true); 
       table.setPreferredSize(new Dimension(500, 300)); 

       scroll = new JScrollPane(table); 

       table.setDropTarget(new DropTarget() { 
        @Override 
        public synchronized void dragOver(DropTargetDragEvent dtde) { 
         Point point = dtde.getLocation(); 
         int row = table.rowAtPoint(point); 
         if (row < 0) { 
          table.clearSelection(); 
         } else { 
          table.setRowSelectionInterval(row, row); 
         } 
         dtde.acceptDrag(DnDConstants.ACTION_COPY_OR_MOVE); 
        } 

        @Override 
        public synchronized void drop(DropTargetDropEvent dtde) { 
         if (dtde.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) 
         {//make sure the flavors are files 
          dtde.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);//dndconstants tells what to do with the drag files 
          //change to ACTION_COPY so it removes the file from the directory 
          Transferable t = dtde.getTransferable(); 
          List fileList = null; 
          try { 
           fileList = (List) t.getTransferData(DataFlavor.javaFileListFlavor);//get file 
           if (fileList.size() > 0) { 
            table.clearSelection(); 
            Point point = dtde.getLocation();//point is (x,y) 
            int row = table.rowAtPoint(point); 
            DefaultTableModel model = (DefaultTableModel) table.getModel(); 
            for (Object value : fileList) { 
             if (value instanceof File) { 
              File f = (File) value; 

              if (row < 0) {//insert rows into the right columns 
              model.addRow(new Object[]{f.getAbsolutePath(), "", f.length(), "", ""});//path under "File" 
              } else { 
               model.insertRow(row, new Object[]{f.getAbsolutePath(), "", f.length(), "", ""});//get size of file 
               row++; 

              } 
             } 
            } 
           } 
          } catch (UnsupportedFlavorException e) { 
           e.printStackTrace(); 
          } catch (IOException e) { 
           e.printStackTrace(); 
          } 
         } else { 
          dtde.rejectDrop(); 
         } 
        } 

       }); 

       add(scroll, BorderLayout.CENTER); 
      } 
     } 
    } 

Antwort

22

Hier ist ein einfaches Beispiel, das im Grunde ein SwingWorker verwendet das Stammverzeichnis des Laufwerks zu scannen und listet alle Dateien. Sobald dies abgeschlossen ist, wird es versucht, jede Datei zu lesen, in seiner eigenen SwingWorker Aktualisierung der Tabelle, wie es geht.

Haftungsausschluss: Dies ist ein Beispiel. Ich benutze Thread.sleep, um die Lesevorgänge etwas zu verlangsamen, die Puffer zu ignorieren und ein paar andere Dinge, die ich im Produktionscode anders machen würde, aber ich wollte die Fortschrittsaktualisierungen hervorheben.

enter image description here

Wie es

Zuerst arbeitet, benötigen Sie einen CellRenderers Lage Fortschritt Updates angezeigt werden kann. Ich habe eine einfache benutzerdefinierte JProgressBar gewählt, aber vielleicht möchten Sie etwas anspruchsvoller.

Sie benötigen eine Möglichkeit, das Tabellenmodell zu aktualisieren. Ich habe gewählt, um eine einfache updateStatus Methode zur Verfügung zu stellen, die Datei übergebe, die ich aktualisiere, erlaubt mir, interne Nachschlagen zu verwenden, um die fragliche Reihe zu finden. Ich verwende dann die setValueAt Methode, um das Zeilenobjekt zu aktualisieren. Dies ist nicht wirklich erforderlich, aber ich wollte die Verwendung der setValueAt-Methode demonstrieren, Sie hätten das Zeilenobjekt von der updateStatus-Methode direkt aktualisieren können.

Und schließlich, melden Sie die Tabelle der Änderungen an dem Modell, so dass es sich neu streichen wird.

public class UpdateTable { 

    public static void main(String[] args) { 
     new UpdateTable(); 
    } 

    public UpdateTable() { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       try { 
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
       } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { 
       } 

       UpdatableTableModel model = new UpdatableTableModel(); 

       JTable table = new JTable(); 
       table.setModel(model); 

       table.getColumn("Status").setCellRenderer(new ProgressCellRender()); 

       JFrame frame = new JFrame(); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       frame.setLayout(new BorderLayout()); 
       frame.add(new JScrollPane(table)); 
       frame.pack(); 
       frame.setLocationRelativeTo(null); 
       frame.setVisible(true); 

       FileFinderWorker worker = new FileFinderWorker(model); 
       worker.execute(); 

      } 
     }); 
    } 

    public class ProgressCellRender extends JProgressBar implements TableCellRenderer { 

     @Override 
     public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { 
      int progress = 0; 
      if (value instanceof Float) { 
       progress = Math.round(((Float) value) * 100f); 
      } else if (value instanceof Integer) { 
       progress = (int) value; 
      } 
      setValue(progress); 
      return this; 
     } 
    } 

    public class RowData { 

     private File file; 
     private String type; 
     private long length; 
     private float status; 

     public RowData(File file, String type) { 
      this.file = file; 
      this.type = type; 
      this.length = file.length(); 
      this.status = 0f; 
     } 

     public File getFile() { 
      return file; 
     } 

     public long getLength() { 
      return length; 
     } 

     public float getStatus() { 
      return status; 
     } 

     public String getType() { 
      return type; 
     } 

     public void setStatus(float status) { 
      this.status = status; 
     } 
    } 

    public class UpdatableTableModel extends AbstractTableModel { 

     private List<RowData> rows; 
     private Map<File, RowData> mapLookup; 

     public UpdatableTableModel() { 
      rows = new ArrayList<>(25); 
      mapLookup = new HashMap<>(25); 
     } 

     @Override 
     public int getRowCount() { 
      return rows.size(); 
     } 

     @Override 
     public int getColumnCount() { 
      return 4; 
     } 

     @Override 
     public String getColumnName(int column) { 
      String name = "??"; 
      switch (column) { 
       case 0: 
        name = "File"; 
        break; 
       case 1: 
        name = "File Type"; 
        break; 
       case 2: 
        name = "Size"; 
        break; 
       case 3: 
        name = "Status"; 
        break; 
      } 
      return name; 
     } 

     @Override 
     public Object getValueAt(int rowIndex, int columnIndex) { 
      RowData rowData = rows.get(rowIndex); 
      Object value = null; 
      switch (columnIndex) { 
       case 0: 
        value = rowData.getFile(); 
        break; 
       case 1: 
        value = rowData.getType(); 
        break; 
       case 2: 
        value = rowData.getLength(); 
        break; 
       case 3: 
        value = rowData.getStatus(); 
        break; 
      } 
      return value; 
     } 

     @Override 
     public void setValueAt(Object aValue, int rowIndex, int columnIndex) { 
      RowData rowData = rows.get(rowIndex); 
      switch (columnIndex) { 
       case 3: 
        if (aValue instanceof Float) { 
         rowData.setStatus((float) aValue); 
        } 
        break; 
      } 
     } 

     public void addFile(File file) { 
      RowData rowData = new RowData(file, "A File"); 
      mapLookup.put(file, rowData); 
      rows.add(rowData); 
      fireTableRowsInserted(rows.size() - 1, rows.size() - 1); 
     } 

     protected void updateStatus(File file, int progress) { 
      RowData rowData = mapLookup.get(file); 
      if (rowData != null) { 
       int row = rows.indexOf(rowData); 
       float p = (float) progress/100f; 
       setValueAt(p, row, 3); 
       fireTableCellUpdated(row, 3); 
      } 
     } 
    } 

    public class FileFinderWorker extends SwingWorker<List<File>, File> { 

     private UpdatableTableModel model; 

     public FileFinderWorker(UpdatableTableModel model) { 
      this.model = model; 
     } 

     @Override 
     protected void process(List<File> chunks) { 
      for (File file : chunks) { 
       model.addFile(file); 
      } 
     } 

     @Override 
     protected List<File> doInBackground() throws Exception { 
      File files[] = new File(System.getProperty("user.dir")).listFiles(); 
      List<File> lstFiles = new ArrayList<>(Arrays.asList(files)); 
      for (File file : lstFiles) { 
       // You could actually publish the entire array, but I'm doing this 
       // deliberatly ;) 
       publish(file); 
      } 
      return lstFiles; 
     } 

     @Override 
     protected void done() { 
      try { 
       List<File> files = get(); 
       for (File file : files) { 
        new FileReaderWorker(model, file).execute(); 
       } 
      } catch (Exception exp) { 
       exp.printStackTrace(); 
      } 
     } 
    } 

    public class FileReaderWorker extends SwingWorker<File, File> { 

     private File currentFile; 
     private UpdatableTableModel model; 

     public FileReaderWorker(UpdatableTableModel model, File file) { 
      this.currentFile = file; 
      this.model = model; 

      addPropertyChangeListener(new PropertyChangeListener() { 
       @Override 
       public void propertyChange(PropertyChangeEvent evt) { 
        if (evt.getPropertyName().equals("progress")) { 
         FileReaderWorker.this.model.updateStatus(currentFile, (int) evt.getNewValue()); 
        } 
       } 
      }); 

     } 

     @Override 
     protected File doInBackground() throws Exception { 
      if (currentFile.isFile()) { 
       setProgress(0); 
       long fileLength = currentFile.length(); 
       BufferedReader reader = null; 
       char[] cbuf = new char[1024]; 
       try { 
        reader = new BufferedReader(new FileReader(currentFile)); 
        int bytesRead = -1; 
        int totalBytesRead = 0; 
        while ((bytesRead = reader.read(cbuf)) != -1) { 
         totalBytesRead += bytesRead; 
         int progress = (int) Math.round(((double) totalBytesRead/(double) fileLength) * 100d); 
         setProgress(progress); 
         Thread.sleep(25); 
        } 
        setProgress(100); 
       } catch (Exception e) { 
        e.printStackTrace(); 
        setProgress(100); 
       } finally { 
        try { 
         reader.close(); 
        } catch (Exception e) { 
        } 
       } 
      } else { 
       setProgress(100); 
      } 
      return currentFile; 
     } 
    } 
} 

Wichtige Konzepte.

NIEMALS, EVER blockieren den Event Dispatching Thread mit irgendeiner Art von lang andauernden Operation. Verschieben Sie stattdessen diese zeitraubenden Vorgänge in einen Hintergrundthread. Hier habe ich verwendet SwingWorker

Haben Sie einen Lese durch Concurrency in Swing für weitere Informationen

+2

+1 Sehen Sie sich auch 'System.getProperty ("user.dir")' über "C: /". – trashgod

+0

@MadProgrammer Vielen Dank für das Beispiel. Ich freue mich darauf, es auszuführen, aber als ich versuchte, es auszuführen, erhielt ich einen Fehler "kann nicht von Objekt zu int werfen" hier: 'FileReaderWorker.this.model.updateStatus (currentFile, (int) evt.getNewValue());' und hier 'rowData.setStatus ((float) aValue);' – rogerthat

+0

@trashgod Da musste etwas sein: P – MadProgrammer

7

Sie erhalten eine TableCellRenderer benötigen, die eine JProgressBar enthält, wie here gezeigt. Sie können den Fortschritt jeder Datei von einem SwingWorker, gesehen here, aktualisieren.

image

0

Sie brauchen eine Art eines Prozesses mit einem ganzzahligen Wert zwischen 0 und 100 haben:

class Process { 

    public Process(String name, int progress, String description) { 
     super(); 
     this.name = name; 
     this.progress = progress; 
     this.description = description; 
    } 

    String name; 
    int progress; 
    String description; } 

Dies wird in den Tabellen tableModel modelliert.

Ein Renderer benötigt wird, um einen Fortschrittsbalken auf einem der Tische Spalten zurück:

class ProgressRenderer extends DefaultTableCellRenderer { 
    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, 
      boolean hasFocus, int row2, int column) { 

     int row = table.convertRowIndexToModel(row2); 

     ProcessTableModel mtm = (ProcessTableModel) table.getModel(); 
     Process p = (Process) mtm.getProcessAt(row); 

     JProgressBar bar = new JProgressBar(); 
     bar.setValue(p.progress); 
     return bar; 
    } 
} 

Jetzt nur Sie einen Thread brauchen etwas in den Hintergrund zu tun, und der Prozessobjekte zu aktualisieren. Das vollständige Beispiel, von dem ich Codeschnipsel kopiert habe, ist here.

enter image description here

Verwandte Themen