2012-12-06 22 views
10

Aplikacja szyfruje każdy plik, który jest wstawiony do tabeli po kliknięciu przycisku szyfrowania i chcę pokazać postęp plików podczas ich szyfrowania. Kolumna "Status" zmieni się z "Nie przetworzono" na "Przetworzono".Dodawanie paska postępu do każdej komórki tabeli dla postępu pliku - Java

Podobny sposób oglądania wielu plików można załączyć w wiadomości e-mail. Zajmowałem się rendererem komórek i ProgressBarTablecell, ale nie jestem pewien, jak je wdrożyć. Każda pomoc doceniona. Publikuję tabelę.

 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); 
      } 
     } 
    } 

Odpowiedz

22

Oto prosty przykład, to w zasadzie używa SwingWorker skanować katalog główny dysku i wyświetla wszystkie pliki. Gdy to się zakończy, spróbuje odczytać każdy plik, aktualizując tabelę w aktualnym stanie.

Nota prawna: To jest przykład. Używam Thread.sleep, aby nieco spowolnić czytanie, zignorować bufory i kilka innych rzeczy, które zrobiłbym inaczej w kodzie produkcyjnym, ale chciałem podświetlić aktualizacje postępu.

enter image description here

Jak to działa

Po pierwsze, trzeba renderujący komórki zdolnej do wyświetlania aktualizacji postępu. Wybrałem prosty niestandardowy JProgressBar, ale może Ci się spodobać coś bardziej wyrafinowanego.

Potrzebujesz sposobu na aktualizację modelu tabeli. Wybrałem dostarczenie prostej metody updateStatus, przekazując aktualizowany plik, co pozwala mi używać wewnętrznych wyszukiwań, aby znaleźć dany wiersz. Następnie używam metody setValueAt, aby zaktualizować obiekt wiersza. To naprawdę nie jest wymagane, ale chciałem zademonstrować użycie metody setValueAt, można było zaktualizować obiekt wiersza bezpośrednio z metody updateStatus.

Na koniec należy zgłosić tabelę zmian do modelu, aby odświeżyć się.

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; 
     } 
    } 
} 

Ważne pojęcia.

NIGDY nie blokuj wątku wywołującego zdarzenia przy jakiejkolwiek długiej pracy. Zamiast tego przenieś te czasochłonne operacje do wątku tła. Tutaj użyłem SwingWorker

Prosze przeczytać Concurrency in Swing uzyskać więcej informacji

+2

+1 również pod uwagę 'System.getProperty ("")' user.dir nad "C: /". – trashgod

+0

@MadProgrammer Wielkie dzięki za przykład. Nie mogę się doczekać, aby go uruchomić, ale kiedy próbowałem go uruchomić, otrzymałem komunikat o błędzie "Nie mogę przesyłać z obiektu do wnętrza" tutaj: 'FileReaderWorker.this.model.updateStatus (currentFile, (int) evt.getNewValue());' i tutaj 'rowData.setStatus ((float) aValue);' – rogerthat

+0

@trashgod Musiało być coś: P – MadProgrammer

7

Będziesz potrzebował TableCellRenderer zawierający JProgressBar, jak pokazano here. Możesz zaktualizować postęp każdego pliku z poziomu SwingWorker, widzianego here.

image

0

Trzeba mieć jakiś proces o wartość całkowitą z przedziału od 0 do 100. Na przykład:

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; } 

Zostaje to zamodelowane w tabelach tableModel.

renderujący jest potrzebna, aby powrócić do paska postępu na jednej z kolumn tabel:

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; 
    } 
} 

Teraz wystarczy nić się robić coś w tle i aktualizowania obiektów procesowych. Pełny przykład, z którego skopiowałem fragmenty kodu, można znaleźć here.

enter image description here