Java AWT Threads
У меня проблема с потоками, использующими NetBeans Swing GUI. Это мой первый раз, когда я действительно пытаюсь разработать графический интерфейс для программы резервного копирования с использованием Java File Notifier. У меня есть два файлаSyncUI.java
а такжеSync.java
.
Я хочу, чтобы вы ввели путь к каталогу вjTextField1
текстовое поле, которое создает поток синхронизации, который создает новый объект синхронизации и затем вызываетprocessEvents
на этом объекте. Когда файл в этом каталоге изменяется, я хочу добавить текст об изменении в список.
В своем текущем состоянии пользовательский интерфейс больше не отвечает, однакоprocessEvents
ничего не добавляю в мой список. Есть идеи, в чем проблема? Кроме того, поскольку я только начинаю использовать Java, приветствуется любая конструктивная критика.
package sync;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.DefaultListModel;
import javax.swing.JList;
import javax.swing.SwingUtilities;
public class SyncUI extends javax.swing.JFrame {
public SyncUI() {
initComponents();
}
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">
private void initComponents() {
jButton1 = new javax.swing.JButton();
jTextField1 = new javax.swing.JTextField();
list1 = new java.awt.List();
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
jButton1.setText("Start");
jButton1.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jButton1ActionPerformed(evt);
}
});
jTextField1.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jTextField1ActionPerformed(evt);
}
});
list1.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
list1ActionPerformed(evt);
}
});
org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
.add(layout.createSequentialGroup()
.addContainerGap()
.add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
.add(list1, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.add(layout.createSequentialGroup()
.add(jTextField1, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 329, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
.add(jButton1)
.add(0, 0, Short.MAX_VALUE)))
.addContainerGap())
);
layout.setVerticalGroup(
layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
.add(layout.createSequentialGroup()
.addContainerGap()
.add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
.add(jButton1)
.add(jTextField1, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
.add(list1, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 229, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
.addContainerGap(25, Short.MAX_VALUE))
);
pack();
}// </editor-fold>
private void jTextField1ActionPerformed(java.awt.event.ActionEvent evt) {
jButton1.doClick();
}
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
//I tried to use invokeLater, this solved the problem of the UI nonresponse issue
SwingUtilities.invokeLater(new Runnable() {
public void run()
{
//Creates a path dir that my Sync constructor needs to start file notification watcher on that directory
Path dir = Paths.get(jTextField1.getText());
try
{
//Creates a new sync object passing it the directory and the list in my GUI
Sync sync = new Sync(dir, list1);
try
{
sync.processEvents();
}
catch (InterruptedException ex)
{
Logger.getLogger(SyncUI.class.getName()).log(Level.SEVERE, null, ex);
}
}
catch (IOException ex)
{
Logger.getLogger(SyncUI.class.getName()).log(Level.SEVERE, null, ex);
}
}
});
}
private void list1ActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
}
public static void main(String args[]) throws IOException
{
java.awt.EventQueue.invokeLater(new Runnable()
{
public void run()
{
SyncUI s = new SyncUI();
s.setVisible(true);
}
});
}
// Variables declaration - do not modify
private javax.swing.JButton jButton1;
private javax.swing.JTextField jTextField1;
private java.awt.List list1;
// End of variables declaration
}
Sync.java:
package sync;
import static java.nio.file.StandardWatchEventKinds.*;
import java.nio.file.attribute.*;
import java.io.*;
import java.nio.file.*;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.SwingUtilities;
public class Sync
{
private final WatchService ws;
private final Map<WatchKey,Path> keys;
public java.awt.List list;
public Sync(Path dir, java.awt.List list) throws IOException, InterruptedException
{
this.ws = FileSystems.getDefault().newWatchService();
this.keys = new HashMap<WatchKey,Path>();
this.list = list;
recSet(dir);
//this.processEvents();
}
private void register(Path dir) throws IOException
{
WatchKey key = dir.register(ws, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY);
keys.put(key, dir);
}
private void recSet(Path start) throws IOException
{
Files.walkFileTree(start, new SimpleFileVisitor<Path>()
{
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException
{
if(!Files.isHidden(dir))
{
register(dir);
System.out.println(dir);
}
return FileVisitResult.CONTINUE;
}
});
}
void processEvents() throws IOException, InterruptedException
{
System.out.println("Entered processEvents");
SwingUtilities.invokeLater(new Runnable() {
public void run()
{
System.out.println("Entered run");
list.add("test2");
list.repaint();
while(true)
{
WatchKey key;
try
{
key = ws.take();
}
catch (InterruptedException x)
{
return;
}
Path dir = keys.get(key);
if (dir == null)
{
System.err.println("WatchKey not recognized");
continue;
}
for (WatchEvent<?> event: key.pollEvents())
{
WatchEvent.Kind<?> kind = event.kind();
WatchEvent<Path> ev = (WatchEvent<Path>)event;
Path filename = ev.context();
String name = dir.resolve(filename).toString();
if (kind == OVERFLOW)
continue;
if(kind == ENTRY_CREATE)
{
System.out.print("Entry Created: ");
File f = new File(name);
if(f.isDirectory())
try {
register(dir.resolve(filename));
} catch (IOException ex) {
Logger.getLogger(Sync.class.getName()).log(Level.SEVERE, null, ex);
}
System.out.println(name);
list.add(name);
}
else if(kind == ENTRY_DELETE)
{
System.out.print("Entry Deleted: ");
System.out.println(name);
}
else if(kind == ENTRY_MODIFY)
{
File f = new File(name);
if(!f.isDirectory())
{
System.out.print("Entry Modify: ");
System.out.println(name);
}
}
boolean valid = key.reset();
if (!valid)
break;
}
}
}
});
}
}