如何搜索子文件夹并使用Java中的新数据重新绘制jTable?

我的程序遇到了一些问题。 我想让一个jTable显示添加到其TableModel的各种数据点,但我似乎无法使用新数据更新表。

此外,似乎我在目录中搜索png图像实际上没有完全搜索所有png图像的目录,只停在第一个文件夹的内容。

我已将所有数据点放入适当的ArrayLists中以获取其数据类型,并将它们转换为Object数组,然后将它们放入我的jTable的TableModel中。 它没有用,我没有用自己的知识解决这些问题。

一些代码:

private void btnPatchSelActionPerformed(java.awt.event.ActionEvent evt) { fchsFolderChooser.showOpenDialog(null); File selFile = fchsFolderChooser.getSelectedFile(); fldPatchSel.setText(selFile.getPath()); File pngs[] = selFile.listFiles(IMAGE_FILTER); for (File png : pngs) { try {BufferedImage img = ImageIO.read(png); patchWs.add(img.getWidth()); patchHs.add(img.getHeight()); patchDims.add(img.getWidth() + "x" + img.getHeight()); patchImgs.add(img); patchImgPaths.add(png.getPath()); sels.add(false); System.out.println("Found " + png.getPath()); } catch (IOException e) { System.out.println("Bad image: " + png); e.printStackTrace(); } } if(!(fldPatchSel.getText().endsWith("...")||fldModSel.getText().endsWith("..."))) {BuildTable();} } 

mod资产选择的对应部分是类似的,但没有设置sels ArrayList。

 private void BuildTable(){ DefaultTableModel model = (DefaultTableModel) tblImgList.getModel(); Object[] boolSels = sels.toArray(); Object[] stringPatchPaths = patchImgPaths.toArray(); Object[] stringPatchImgDims = patchDims.toArray(); model.addColumn("", boolSels); model.addColumn("Patch Image", stringPatchPaths); model.addColumn("W x H", stringPatchImgDims); tblImgList.repaint(); } 

你怎么解决我的两个问题? 该程序不搜索子文件夹,也无法在表格中显示新数据。

首先,删除DefaultTableModel ,您的数据模型变得复杂。 从POJO(Plain Old Java Object)开始,它包含了你想要显示的内容的上下文…

 public class ImageProperty { private File source; private Dimension size; private boolean selected; public ImageProperty(File source, Dimension size, boolean selected) { this.source = source; this.size = size; this.selected = selected; } public Dimension getSize() { return size; } public File getSource() { return source; } public boolean isSelected() { return selected; } } 

它包含单个图像文件的所有信息,并将用于表示表中行的内容。

其次,创建一个自定义的TableModel 。 这是一种个人的事情,但是使用DefaultTableModel ,你花费更多时间来破解它试图让它做你想做的事情,这将通过使用你自己的…更好地解决…

 public class ImageTableModel extends AbstractTableModel { private List images; public ImageTableModel() { images = new ArrayList(25); } @Override public int getRowCount() { return images.size(); } @Override public int getColumnCount() { return 4; } @Override public String getColumnName(int column) { String name = ""; switch (column) { case 1: name = "Path"; break; case 2: name = "Name"; break; case 3: name = "Size"; break; } return name; } @Override public Class getColumnClass(int columnIndex) { return columnIndex == 0 ? Boolean.class : String.class; } @Override public Object getValueAt(int rowIndex, int columnIndex) { ImageProperty row = images.get(rowIndex); Object value = null; switch (columnIndex) { case 0: value = row.isSelected(); break; case 1: value = row.getSource().getParent(); break; case 2: value = row.getSource().getName(); break; case 3: value = row.getSize().width + "x" + row.getSize().height; break; } return value; } public void addImage(ImageProperty image) { images.add(image); fireTableRowsInserted(images.size() - 1, images.size() - 1); } public void addImages(List newImages) { int firstRow = images.size(); int lastRow = firstRow + newImages.size() - 1; images.addAll(newImages); fireTableRowsInserted(firstRow, lastRow); } public void clear() { int lastRow = images.size() -1; images.clear(); fireTableRowsDeleted(0, lastRow); } } 

第三,不要尝试在事件调度线程中进行目录扫描,这将导致UI“暂停”直到扫描完成,并且根据图像的大小和子目录的数量,可能需要几分钟才能完成。完成。

有关详细信息,请参阅Swing中的并发 …

有许多方法可以解决这个问题,但SwingWorker可能是最简单的,因为它提供了安全地提供更新回EDT的function,因此您可以更新UI而不会引起进一步的问题……

 public class ScanWorker extends SwingWorker { private File source; private ImageTableModel model; public ScanWorker(File source, ImageTableModel model) { this.source = source; this.model = model; } @Override protected void process(List chunks) { model.addImages(chunks); } @Override protected Object doInBackground() throws Exception { scan(source); return null; } protected void scan(File dir) { firePropertyChange("directory", dir.getParent(), dir); File pngs[] = dir.listFiles(new FileFilter() { @Override public boolean accept(File pathname) { return pathname.getName().toLowerCase().endsWith(".png"); } }); for (File png : pngs) { try { BufferedImage img = ImageIO.read(png); publish(new ImageProperty(png, new Dimension(img.getWidth(), img.getHeight()), false)); } catch (IOException e) { System.out.println("Bad image: " + png); e.printStackTrace(); } } File dirs[] = dir.listFiles(new FileFilter() { @Override public boolean accept(File pathname) { return pathname.isDirectory(); } }); if (dirs != null && dirs.length > 0) { for (File subDir : dirs) { scan(subDir); } } } } 

这个worker使用递归方法调用来扫描子目录……

最后胶水……

此代码段禁用“扫描”按钮,清除当前表模型,创建SwingWorker并向其注册PropertyChangeListener ,最后启动工作程序…

 model.clear(); scan.setEnabled(false); ScanWorker worker = new ScanWorker(new File("..."), model); worker.addPropertyChangeListener(new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent evt) { if ("state".equalsIgnoreCase(evt.getPropertyName())) { SwingWorker.StateValue state = (SwingWorker.StateValue) evt.getNewValue(); scan.setEnabled(state == SwingWorker.StateValue.DONE); scan.setText("Scan"); } else if ("directory".equalsIgnoreCase(evt.getPropertyName())) { scan.setText(text); } } }); worker.execute(); 

PropertyChangeListener监视工作者状态的更改,并在完成时将按钮重置为启用。 它还监视扫描目录的更改并更新按钮的文本以反映当前已处理的目录…很好

上面的代码片段由附加到“scan”按钮的ActionListener触发

还有一个很好的可运行的例子……

扫描

 import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.EventQueue; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.image.BufferedImage; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.io.File; import java.io.FileFilter; import java.io.IOException; import java.util.ArrayList; import java.util.List; import javax.imageio.ImageIO; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.SwingWorker; import javax.swing.UIManager; import javax.swing.UnsupportedLookAndFeelException; import javax.swing.table.AbstractTableModel; public class ShowImages { public static void main(String[] args) { new ShowImages(); } public ShowImages() { EventQueue.invokeLater(new Runnable() { @Override public void run() { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { ex.printStackTrace(); } final ImageTableModel model = new ImageTableModel(); JTable table = new JTable(model); final JButton scan = new JButton("Scan"); scan.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { model.clear(); scan.setEnabled(false); ScanWorker worker = new ScanWorker(new File("C:\\Users\\shane\\Dropbox\\MegaTokyo"), model); worker.addPropertyChangeListener(new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent evt) { if ("state".equalsIgnoreCase(evt.getPropertyName())) { SwingWorker.StateValue state = (SwingWorker.StateValue) evt.getNewValue(); scan.setEnabled(state == SwingWorker.StateValue.DONE); scan.setText("Scan"); } else if ("directory".equalsIgnoreCase(evt.getPropertyName())) { String text = ((File)evt.getNewValue()).getPath().replaceAll("shane", "..."); text = text.replaceAll("C:\\\\", "..."); text = text.replaceAll("Dropbox", "..."); scan.setText(text); } } }); worker.execute(); } }); JFrame frame = new JFrame("Testing"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.add(new JScrollPane(table)); frame.add(scan, BorderLayout.SOUTH); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); } }); } public class ImageProperty { private File source; private Dimension size; private boolean selected; public ImageProperty(File source, Dimension size, boolean selected) { this.source = source; this.size = size; this.selected = selected; } public Dimension getSize() { return size; } public File getSource() { return source; } public boolean isSelected() { return selected; } } public class ImageTableModel extends AbstractTableModel { private List images; public ImageTableModel() { images = new ArrayList(25); } @Override public int getRowCount() { return images.size(); } @Override public int getColumnCount() { return 4; } @Override public String getColumnName(int column) { String name = ""; switch (column) { case 1: name = "Path"; break; case 2: name = "Name"; break; case 3: name = "Size"; break; } return name; } @Override public Class getColumnClass(int columnIndex) { return columnIndex == 0 ? Boolean.class : String.class; } @Override public Object getValueAt(int rowIndex, int columnIndex) { ImageProperty row = images.get(rowIndex); Object value = null; switch (columnIndex) { case 0: value = row.isSelected(); break; case 1: value = row.getSource().getParent(); break; case 2: value = row.getSource().getName(); break; case 3: value = row.getSize().width + "x" + row.getSize().height; break; } return value; } public void addImage(ImageProperty image) { images.add(image); fireTableRowsInserted(images.size() - 1, images.size() - 1); } public void addImages(List newImages) { int firstRow = images.size(); int lastRow = firstRow + newImages.size() - 1; images.addAll(newImages); fireTableRowsInserted(firstRow, lastRow); } public void clear() { int lastRow = images.size() -1; images.clear(); fireTableRowsDeleted(0, lastRow); } } public class ScanWorker extends SwingWorker { private File source; private ImageTableModel model; public ScanWorker(File source, ImageTableModel model) { this.source = source; this.model = model; } @Override protected void process(List chunks) { model.addImages(chunks); } @Override protected Object doInBackground() throws Exception { scan(source); return null; } protected void scan(File dir) { firePropertyChange("directory", dir.getParent(), dir); File pngs[] = dir.listFiles(new FileFilter() { @Override public boolean accept(File pathname) { return pathname.getName().toLowerCase().endsWith(".png"); } }); for (File png : pngs) { try { BufferedImage img = ImageIO.read(png); publish(new ImageProperty(png, new Dimension(img.getWidth(), img.getHeight()), false)); } catch (IOException e) { System.out.println("Bad image: " + png); e.printStackTrace(); } } File dirs[] = dir.listFiles(new FileFilter() { @Override public boolean accept(File pathname) { return pathname.isDirectory(); } }); if (dirs != null && dirs.length > 0) { for (File subDir : dirs) { scan(subDir); } } } } } 

有关详细信息,请查看Worker Threads和SwingWorker