假设我有一个文件夹C:stuff
。在stuff
中,有数千个杂项文件和其他文件夹。
在Windows中,我只需转到文件夹,右键单击它并单击属性,取消设置只读标志,然后将操作应用于父文件夹、所有子文件夹和所有文件。
然而,我想在Java中通过在GUI中简单地单击JButton
来实现自动化。ActionListener
内部的代码会是什么样子?有可能做到这一点吗?有什么我可以利用的吗,比如让Java
写入PowerShell
或cmd
?
您可以使用Files.walkFileTree来执行此操作,但如果您在ActionListener(或从ActionListener调用的任何方法)中执行该操作,则在更改文件时,您的应用程序将被冻结。这是因为ActionListener是在事件调度线程上调用的,该线程与执行键盘输入、鼠标输入和屏幕绘制的线程相同。因此,当您在该线程中执行耗时的操作时,您的应用程序将忽略键盘输入和鼠标输入,如果它在视觉上被任何其他移动或关闭的应用程序遮挡,它将不会重新绘制自己。
如果您不关心应用程序是否挂起,您可以在ActionListener:中执行操作
Files.walkFileTree(rootDirectory, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult preVisitDirectory(Path dir,
BasicFileAttributes attr)
throws IOException {
Files.setAttribute(dir, "dos:readonly", false);
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult visitFile(Path file,
BasicFileAttributes attr)
throws IOException {
Files.setAttribute(file, "dos:readonly", false);
return FileVisitResult.CONTINUE;
}
});
但实际上,您不应该挂起事件调度线程。文件I/O应该在另一个线程中完成。有很多方法可以做到这一点,但SwingWorker似乎对许多人来说是最简单的:
static void updateReadOnlyInTree(final Path root,
Window parentWindow) {
SwingWorker<Void, Integer> worker = new SwingWorker<Void, Integer>() {
@Override
public Void doInBackground()
throws IOException {
Files.walkFileTree(root, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult preVisitDirectory(
Path dir,
BasicFileAttributes attr)
throws IOException {
Files.setAttribute(dir, "dos:readonly", false);
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult visitFile(Path file,
BasicFileAttributes attr)
throws IOException {
Files.setAttribute(file, "dos:readonly", false);
return FileVisitResult.CONTINUE;
}
});
return null;
}
};
final JOptionPane waitPane = new JOptionPane("Updating filesu2026",
JOptionPane.INFORMATION_MESSAGE);
final JDialog waitDialog =
waitPane.createDialog(parentWindow, "Files Update");
worker.addPropertyChangeListener(new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent event) {
if (event.getPropertyName().equals("state") &&
event.getNewValue() == SwingWorker.StateValue.DONE) {
waitPane.setValue(JOptionPane.CLOSED_OPTION);
}
}
});
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
waitDialog.setVisible(true);
}
});
worker.execute();
}
您甚至可以更进一步,在更改任何文件之前对其进行计数,然后使用ProgressMonitor而不是JOptionPane。