java - 单击搜索按钮后 JList 不填充

标签 java swing jlist

我在 java GUI 应用程序中编写了一个递归搜索方法来查找驱动器中的文件。
UI 响应迅速,
搜索成功,但 JList 未填充,而控制台成功打印文件名,单击搜索按钮 3 次后,文件将添加到 JList 中,但每个文件的名称重复

     //nullpointerexception
      java.util.concurrent.ExecutionException:  
    java.lang.NullPointerException
at java.util.concurrent.FutureTask.report(FutureTask.java:122)
at java.util.concurrent.FutureTask.get(FutureTask.java:188)
at javax.swing.SwingWorker.get(SwingWorker.java:602)
at searchapp.searchScreen$4.propertyChange(searchScreen.java:90)
at java.beans.PropertyChangeSupport.fire(PropertyChangeSupport.java:335)
atjava.beans.PropertyChangeSupport.firePropertyChange(PropertyChangeSupport.java:327)
at javax.swing.SwingWorker$SwingWorkerPropertyChangeSupport.firePropertyChange(SwingWorker.java:854)
at javax.swing.SwingWorker$SwingWorkerPropertyChangeSupport$1.run(SwingWorker.java:859)
at javax.swing.SwingWorker$DoSubmitAccumulativeRunnable.run(SwingWorker.java:832)
at sun.swing.AccumulativeRunnable.run(AccumulativeRunnable.java:112)
at javax.swing.SwingWorker$DoSubmitAccumulativeRunnable.actionPerformed(SwingWorker.java:842)
at javax.swing.Timer.fireActionPerformed(Timer.java:312)
at javax.swing.Timer$DoPostEvent.run(Timer.java:244)
at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:312)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:738)
at java.awt.EventQueue.access$300(EventQueue.java:103)
at java.awt.EventQueue$3.run(EventQueue.java:699)
at java.awt.EventQueue$3.run(EventQueue.java:697)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:708)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:242)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:161)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:150)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:146)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:138)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:91)
Caused by: java.lang.NullPointerException
at searchapp.searchWorker.search(searchWorker.java:65)
at searchapp.searchWorker.search(searchWorker.java:66)
at searchapp.searchWorker.search(searchWorker.java:66)
at searchapp.searchWorker.doInBackground(searchWorker.java:51)
at searchapp.searchWorker.doInBackground(searchWorker.java:21)
at javax.swing.SwingWorker$1.call(SwingWorker.java:296)
at java.util.concurrent.FutureTask.run(FutureTask.java:262)
at javax.swing.SwingWorker.run(SwingWorker.java:335)
at   java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at            java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:745)
java.util.concurrent.ExecutionException: java.lang.NullPointerException
at java.util.concurrent.FutureTask.report(FutureTask.java:122)
at java.util.concurrent.FutureTask.get(FutureTask.java:188)
at javax.swing.SwingWorker.get(SwingWorker.java:602)
at searchapp.searchScreen$4.propertyChange(searchScreen.java:90)
at java.beans.PropertyChangeSupport.fire(PropertyChangeSupport.java:335)
at java.beans.PropertyChangeSupport.firePropertyChange(PropertyChangeSupport.java:327)
at javax.swing.SwingWorker$SwingWorkerPropertyChangeSupport.firePropertyChange(SwingWorker.java:854)
at javax.swing.SwingWorker$SwingWorkerPropertyChangeSupport$1.run(SwingWorker.java:859)
at javax.swing.SwingWorker$DoSubmitAccumulativeRunnable.run(SwingWorker.java:832)
at sun.swing.AccumulativeRunnable.run(AccumulativeRunnable.java:112)
at javax.swing.SwingWorker$DoSubmitAccumulativeRunnable.actionPerformed(SwingWorker.java:842)
at javax.swing.Timer.fireActionPerformed(Timer.java:312)
at javax.swing.Timer$DoPostEvent.run(Timer.java:244)
at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:312)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:738)
at java.awt.EventQueue.access$300(EventQueue.java:103)
at java.awt.EventQueue$3.run(EventQueue.java:699)
at java.awt.EventQueue$3.run(EventQueue.java:697)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:708)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:242)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:161)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:150)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:146)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:138)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:91)
Caused by: java.lang.NullPointerException
at searchapp.searchWorker.search(searchWorker.java:65)
at searchapp.searchWorker.search(searchWorker.java:66)
at searchapp.searchWorker.search(searchWorker.java:66)
at searchapp.searchWorker.doInBackground(searchWorker.java:51)
at searchapp.searchWorker.doInBackground(searchWorker.java:21)
at javax.swing.SwingWorker$1.call(SwingWorker.java:296)
at java.util.concurrent.FutureTask.run(FutureTask.java:262)
at javax.swing.SwingWorker.run(SwingWorker.java:335)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:745)


     //New Code

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

    protected static final FileFilter DIRRECTORY_FILE_FILTER = new FileFilter() {

        @Override
        public boolean accept(File pathname) {
            return pathname.isDirectory();
        }
    };
    private DefaultListModel model;
    private File path;
    private FileFilter filefilter;

    public searchWorker(File path, FileFilter filter, DefaultListModel model) {
        this.model = model;
        this.path = path;
        this.filefilter = filter;
    }

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

    @Override
    protected List<File> doInBackground() throws Exception {
        return new ArrayList<>(search(path));
    }

    public List<File> search(File path) {
        List<File> files = new ArrayList<>(25);
        if (path.exists()) {
            File[] list = path.listFiles(filefilter);
            if (list != null && list.length > 0) {
                files.addAll(Arrays.asList(list));
                publish(list);

            }
            File[] dirs = path.listFiles(DIRRECTORY_FILE_FILTER);
            for (File dir : dirs) {
                files.addAll(search(dir));

            }
        }
        return files;
    }

}

private void searchBtnActionPerformed(java.awt.event.ActionEvent evt) {
    searchWorker worker = new searchWorker(new File("c:\\"), new FileFilter() {

        @Override
        public boolean accept(File pathname) {
            return pathname.getName().endsWith(".txt") && pathname.getName().startsWith("abc");
        }
    }, lm);
    worker.execute();
}

 //old code
DefaultListModel lm = new DefaultListModel();

public void search(String path) {

    File root = new File(path);
    File[] list = root.listFiles();
    if (list == null) {
        return;
    }
    for (File f : list) {
        if (f.isDirectory()) {
            if (list == null) {
                return;
            }
            search(f.getAbsolutePath());

        } else {
            if (f.getName().endsWith(".txt") && f.getName().startsWith("abc")) {
                lm.addElement(f.getName());

                System.out.println(f.getName());

                found = true;
            }
        }

    }


private void formWindowOpened(java.awt.event.WindowEvent evt) {

    jList1.setModel(lm);
}

private void searchBtnActionPerformed(java.awt.event.ActionEvent evt) {
    //just added this code in my program to resolve unresponsive UI
    Thread t = new Thread(new Runnable() {

        @Override
        public void run() {
            search("c:\\");
        }
    });
    t.start();

}

最佳答案

基本问题是,无论如何,您实际上并没有修改 ListModel

Swing 是单线程环境,您使用了 Thread 来确保执行搜索时 UI 不会被阻塞,这很好,但 Swing 也不是线程安全的,这意味着您不应该从事件调度线程的上下文之外更新 UI,因此 Thread 很糟糕。

虽然您“可以”使用Thread,但SwingWorker将为问题提供更好(而且通常更简单)的解决方案(更不用说更可重用的解决方案)

public static class SearchWorker extends SwingWorker<List<File>, File> {

    protected static final FileFilter DIRECTORY_FILE_FILTER = new FileFilter() {
        @Override
        public boolean accept(File pathname) {
            return pathname.isDirectory();
        }
    };

    private DefaultListModel model;
    private File path;
    private FileFilter fileFilter;

    public SearchWorker(File path, FileFilter filter, DefaultListModel model) {
        this.model = model;
        this.path = path;
        this.fileFilter = filter;
    }

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

    @Override
    protected List<File> doInBackground() throws Exception {
        return new ArrayList<>(search(path));
    }

    public List<File> search(File path) {

        List<File> files = new ArrayList<>(25);
        if (path.exists() && path.isDirectory()) {
            File[] list = path.listFiles(fileFilter);
            if (list != null && list.length > 0) {
                files.addAll(Arrays.asList(list));
                publish(list);
            }

            File[] dirs = path.listFiles(DIRECTORY_FILE_FILTER);
            if (dirs != null) {
                for (File dir : dirs) {
                    files.addAll(search(dir));
                }
            }
        }

        return files;
    }

}

然后你只需使用类似的东西来启动它......

SearchWorker worker = new SearchWorker(new File("c:\\"), new FileFilter() {

    @Override
    public boolean accept(File pathname) {
        return pathname.getName().endsWith(".txt") && pathname.getName().startsWith("abc");
    }
}, lm);
worker.execute();

参见Worker Threads and SwingWorker了解更多详情

可运行示例...

Scanning

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.io.FileFilter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.swing.DefaultListModel;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingWorker;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Test {

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

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

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        public TestPane() {
            DefaultListModel model = new DefaultListModel();
            JList list = new JList(model);
            setLayout(new BorderLayout());
            add(new JScrollPane(list));

            JLabel label = new JLabel("...");
            add(label, BorderLayout.SOUTH);

            SearchWorker worker = new SearchWorker(new File("c:\\"), new FileFilter() {
                @Override
                public boolean accept(File pathname) {
                    return pathname.getName().endsWith(".png");
                }
            }, model);
            worker.addPropertyChangeListener(new PropertyChangeListener() {
                @Override
                public void propertyChange(PropertyChangeEvent evt) {
                    SearchWorker worker = (SearchWorker) evt.getSource();
                    if ("state".equals(evt.getPropertyName())) {
                        if (worker.isDone()) {
                            label.setText("Finished");
                            try {
                                List<File> files = worker.get();
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                        }
                    } else if ("path".equals(evt.getPropertyName())) {
                        File path = (File) evt.getNewValue();
                        label.setText(path.toString());
                    }
                }
            });
            worker.execute();
        }

    }

    public static class SearchWorker extends SwingWorker<List<File>, File> {

        protected static final FileFilter DIRECTORY_FILE_FILTER = new FileFilter() {
            @Override
            public boolean accept(File pathname) {
                return pathname.isDirectory();
            }
        };

        private DefaultListModel model;
        private File path;
        private FileFilter fileFilter;

        public SearchWorker(File path, FileFilter filter, DefaultListModel model) {
            this.model = model;
            this.path = path;
            this.fileFilter = filter;
        }

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

        @Override
        protected List<File> doInBackground() throws Exception {
            return new ArrayList<>(search(path));
        }

        public List<File> search(File path) {
            firePropertyChange("path", null, path);
            List<File> files = new ArrayList<>(25);
            if (path.exists() && path.isDirectory()) {
                File[] list = path.listFiles(fileFilter);
                if (list != null && list.length > 0) {
                    files.addAll(Arrays.asList(list));
                    publish(list);
                }

                File[] dirs = path.listFiles(DIRECTORY_FILE_FILTER);
                if (dirs != null) {
                    for (File dir : dirs) {
                        files.addAll(search(dir));
                    }
                }
            }

            return files;
        }

    }

}

关于java - 单击搜索按钮后 JList 不填充,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31010273/

相关文章:

java - 如何获取在使用 JOptionPane.showOptionDialog 时单击了哪个选项?为什么会出现不兼容类型错误

java - 谁能告诉我此查询中 spring-data 投影警告的原因吗?

java - 将数组元素与同一数组的元素合并

java - 无法启动守护进程。请问我该如何解决

Java showInputDialog 选择自定义文本

java - paintComponent() 仅在最小化-最大化屏幕时被调用

java - 在 Applet 中显示 JList

java - 在 JPanel 中设置组件大小

java - 在 Swing Java 中向 JList 添加元素

java - JList setListData 线程问题