0

I'm looking for some help in customizing the JFileChooser.getSelectedFile() method in the code that follows. I'm looking into handling exceptions for this class. Everything is fine but I have found that when running the program and the dialogue prompts to browse and select a directory, if I type a directory into the folder name box that doesn't exist a null pointer exception is thrown.

What I could do to avoid this NullPointerException from being thrown would be to disable the ability to type into the folder name box. This would mean only directories listed in the browse box could be selected. Is there a way to disable the ability to type in the folder name box? If not, does anyone have any suggestions? I would prefer to be able to disable typing in the folder name box so I'm lead to the idea that maybe I can change that box from a text box to a display panel or something.

Code:

public String getAbsoluteDirectoryPath(){
        // display file chooser dialog
        JFileChooser jfc = new JFileChooser();

        // only display directories (folders)
        jfc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);

        // show the dialog
        jfc.showOpenDialog(this);

        // return the selected directory, if one is chosen; otherwise,
        // return null
        if (jfc.getSelectedFile() != null)
        {
            return jfc.getSelectedFile().getAbsolutePath();
        }
        else
        {
            return null;
        }
    }

Exception:

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at directorylister.DirectoryLister.enumerateDirectory(DirectoryLister.java:88)
at directorylister.DirectoryLister.showDirectoryContents(DirectoryLister.java:77)
at directorylister.DirectoryLister.selectDirectory(DirectoryLister.java:65)
at directorylister.GUI$ButtonHandler.actionPerformed(GUI.java:336)
at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2018)
at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2341)
at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:402)
at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:259)
at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:252)
at java.awt.Component.processMouseEvent(Component.java:6516)
at javax.swing.JComponent.processMouseEvent(JComponent.java:3321)
at java.awt.Component.processEvent(Component.java:6281)
at java.awt.Container.processEvent(Container.java:2229)
at java.awt.Component.dispatchEventImpl(Component.java:4872)
at java.awt.Container.dispatchEventImpl(Container.java:2287)
at java.awt.Component.dispatchEvent(Component.java:4698)
at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4832)
at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4492)
at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4422)
at java.awt.Container.dispatchEventImpl(Container.java:2273)
at java.awt.Window.dispatchEventImpl(Window.java:2719)
at java.awt.Component.dispatchEvent(Component.java:4698)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:740)
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.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:87)
at java.awt.EventQueue$4.run(EventQueue.java:713)
at java.awt.EventQueue$4.run(EventQueue.java:711)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:710)
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)

Complete code:

package directorylister;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;

import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingConstants;
import javax.swing.UIManager;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;

/**
 * GUI for Module 3 DirectoryLister assignment
 * 
 * Simple interface that allows user to select a directory using a file chooser
 * dialog, and display all the files and folders in the selected directory
 */
public class GUI extends JFrame
{

    // -----------------------------------------------------------------------
    // Attributes
    // -----------------------------------------------------------------------

    /** Event handler for button click events. */
    private ButtonHandler buttonHandler;

    /** Container for displaying Browse button and address of selected directory */
    private JPanel addressPanel;

    /** Text container for displaying address of selected directory */
    private JLabel addressLabel;

    /** Button for bringing up file chooser dialog */
    private JButton browseButton;

    /** Underlying model for the JTable that displays contents of selected directory */ 
    private DefaultTableModel tableModel;

    /** Table that displays contents of selected directory */
    private JTable directoryContentsTable;

    /** Allows filesTable to be scrollable */
    private JScrollPane tablePane;

    /** Object containing non-GUI logic for program */
    private DirectoryLister model;

    public GUI()
    {
        // use small default size for low-res screens
        setSize(800, 600);

        // set value for title bar of window
        setTitle("Directory Lister");

        // allows the program to exit when the window is closed
        addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent e) {
                dispose();
                System.exit(0);
            }
        });

        // create window components
        initGUI();

        // make sure everything is visible 
        validate();
        repaint();
        setVisible(true);
    }

    private void initGUI()
    {
        // use standard BorderLayout for the window itself
        setLayout(new BorderLayout());

        // event handler for button clicks
        buttonHandler = new ButtonHandler();

        // create text label for displaying selected directory
        addressLabel = new JLabel();

        // create Browse button
        browseButton = new JButton("Browse...");
        browseButton.addActionListener(buttonHandler);

        // create panel for showing Browse button and value for selected directory
        addressPanel = new JPanel();

        // ensure components are laid out from left to right
        addressPanel.setLayout(new FlowLayout(FlowLayout.LEFT));

        // add components to addressPanel
        addressPanel.add(browseButton);
        addressPanel.add(addressLabel);

        // create the table for displaying the directory contents
        createDirectoryContentsTable();

        // make sure table is scrollable
        tablePane = new JScrollPane(directoryContentsTable);

        // add components to main window
        add(addressPanel, BorderLayout.NORTH);
        add(tablePane, BorderLayout.CENTER);
    }

    private void createDirectoryContentsTable()
    {
        // create underlying model for table that displays contents of selected directory
        tableModel = new DefaultTableModel();

        // table model has 4 columns, to display: file/folder name, size (files only), type (file or folder), and date last modified 
        tableModel.addColumn("Name");
        tableModel.addColumn("Size");
        tableModel.addColumn("Type");
        tableModel.addColumn("Date Modified");

        // create GUI table component
        directoryContentsTable = new JTable(tableModel);

        // disallow reordering of table columns
        directoryContentsTable.getTableHeader().setReorderingAllowed(false);

        // create a TableCellRenderer for displaying left justified text
        DefaultTableCellRenderer leftJustifiedRenderer = new DefaultTableCellRenderer();
        leftJustifiedRenderer.setHorizontalAlignment(SwingConstants.LEFT);

        // create a TableCellRenderer for displaying right justified text
        DefaultTableCellRenderer rightJustifiedRenderer = new DefaultTableCellRenderer();
        rightJustifiedRenderer.setHorizontalAlignment(SwingConstants.RIGHT);

        // set cell renderers for data cells
        directoryContentsTable.getColumn("Name").setCellRenderer(leftJustifiedRenderer);
        directoryContentsTable.getColumn("Size").setCellRenderer(rightJustifiedRenderer);
        directoryContentsTable.getColumn("Type").setCellRenderer(leftJustifiedRenderer);
        directoryContentsTable.getColumn("Date Modified").setCellRenderer(leftJustifiedRenderer);

        // create and format headers for column that displays file/folder names
        JLabel nameLabel = new JLabel(" Name", SwingConstants.LEFT);
        nameLabel.setBorder(UIManager.getBorder("TableHeader.cellBorder"));

        directoryContentsTable.getColumn("Name").setHeaderRenderer(new CustomTableCellRenderer());
        directoryContentsTable.getColumn("Name").setHeaderValue(nameLabel);

        // create and format header for column that displays file/folder sizes
        JLabel sizeLabel = new JLabel("Size ", SwingConstants.RIGHT);
        sizeLabel.setBorder(UIManager.getBorder("TableHeader.cellBorder"));

        directoryContentsTable.getColumn("Size").setHeaderRenderer(new CustomTableCellRenderer());
        directoryContentsTable.getColumn("Size").setHeaderValue(sizeLabel);

        // create and format header for column that displays file/folder types
        JLabel typeLabel = new JLabel(" Type", SwingConstants.LEFT);
        typeLabel.setBorder(UIManager.getBorder("TableHeader.cellBorder"));

        directoryContentsTable.getColumn("Type").setHeaderRenderer(new CustomTableCellRenderer());
        directoryContentsTable.getColumn("Type").setHeaderValue(typeLabel);

        // create and format header for column that displays dates last modified for files/folders
        JLabel dateModifiedLabel = new JLabel(" Date Modified", SwingConstants.LEFT);
        dateModifiedLabel.setBorder(UIManager.getBorder("TableHeader.cellBorder"));

        directoryContentsTable.getColumn("Date Modified").setHeaderRenderer(new CustomTableCellRenderer());
        directoryContentsTable.getColumn("Date Modified").setHeaderValue(dateModifiedLabel);
    }

    public void registerModel(DirectoryLister model)
    {
        this.model = model;
    }

    public String getAbsoluteDirectoryPath()
    {
        // display file chooser dialog
        JFileChooser jfc = new JFileChooser();

        // only display directories (folders)
        jfc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);

        // show the dialog
        jfc.showOpenDialog(this);

        // return the selected directory, if one is chosen; otherwise, return null
        if (jfc.getSelectedFile() != null)
        {
            return jfc.getSelectedFile().getAbsolutePath();
        }
        else
        {
            return null;
        }
    }

    public void setAddressLabelText(String text)
    {
        addressLabel.setText(text);
    }

    public void updateListing(String absolutePath, String size, String type, String dateLastModified)
    {
        // add information in new row in table
        tableModel.addRow(new String[] {" " + absolutePath,
                                        size + " ",
                                        " " + type,
                                        " " + dateLastModified});
    }

    public void resetGUI()
    {
        // clear address
        addressLabel.setText("");

        // remove all rows from table
        while (tableModel.getRowCount() > 0)
        {
            tableModel.removeRow(0);
        }
    }

    class CustomTableCellRenderer implements TableCellRenderer
    {
        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,
                                                       boolean hasFocus, int row, int column)
        {
            return (JComponent)value;
        }
    }

    class ButtonHandler implements ActionListener
    {
        public void actionPerformed(ActionEvent e)
        {
            JButton b = (JButton)e.getSource();

            if (b.getText().equals("Browse..."))
            {
                // prompt user to select directory
                model.selectDirectory();
            }
        }
    }
}

package directorylister;

import java.io.*;
import java.text.SimpleDateFormat;
import java.util.*;
import java.awt.*;
import javax.swing.*;

public class DirectoryLister
{
    /** GUI used to display results */
    private GUI gui; 

    /** base path of directory to be traversed */
    private String basePath;

    public DirectoryLister(GUI gui)
    {
        this.gui = gui;
    }

    /**
     *  Allow user to select a directory for traversal.
     */
    public void selectDirectory()
    {
        // clear results of any previous traversal
        gui.resetGUI();

        // allow user to select a directory from the file system
        basePath = gui.getAbsoluteDirectoryPath();

        // update the address label on the GUI
        gui.setAddressLabelText(basePath);

        // traverse the selected directory, and display the contents
        showDirectoryContents(basePath);
    }

    public void showDirectoryContents(String basePath){
        File basePathFile = new File(basePath);
        enumerateDirectory(basePathFile);
    }

    /**
     *  Recursive method to enumerate the contents of a directory.
     *
     *  @param  f   directory to enumerate
     */
    private void enumerateDirectory(File f)
    {
        File[] files = f.listFiles();
        for (File file : files) {
            if (file.isDirectory()) {
                file.getAbsolutePath();
                String fSize = getSizeString(file.length());
                String fType = "Directory";
                String fDate = formattedDateString(file.lastModified());
                gui.updateListing(file.getAbsolutePath(), fSize, fType, fDate);
                enumerateDirectory(file);
            }
            else
                for(int i = 0; i < files.length && files[i].isDirectory()==false; i++) {
                    file.getAbsolutePath();
                    String fSize = getSizeString(file.length());
                    String fType = "File";
                    String fDate = formattedDateString(file.lastModified());
                    gui.updateListing(file.getAbsolutePath(), fSize, fType, fDate);   
                }
        }
    }

    private String getSizeString(long size)
    {
        long kbSize = size / 1024;
        if (kbSize < 1) {     
            return "File size is " + size + " bytes";
        }
        else {
            return "File size is " + kbSize + "KB";
        }
    }

    private String formattedDateString(long time)
    {
        // create Date object from numeric time
        Date d = new Date(time);

        // create formatter
        SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy hh:mm:ss aaa");

        // return formatted date string
        return sdf.format(d);
    }
}
Tom
  • 16,842
  • 17
  • 45
  • 54
JNicholas76
  • 31
  • 10
  • When you ask about an exception, ALWAYS paste (and read) the complete stack trace of the exception, and the relevant code. – JB Nizet Feb 04 '15 at 21:35
  • OK, I thought that was straightforward enough. I will paste it but can't imagine how it would help..... – JNicholas76 Feb 04 '15 at 21:37
  • I know what is happening, but can't seem to find a method in the JFileChooser class that can disable the text box where I am typing the non-existing file. – JNicholas76 Feb 04 '15 at 21:40
  • It is helpful as it tells us which line throws the NPE. Here it's `directorylister.DirectoryLister.enumerateDirectory(DirectoryLister.java:88)`, or line 88 of DirectoryLister.java. Which line is that? – Hovercraft Full Of Eels Feb 04 '15 at 21:40
  • It is indeed straightforward: as the stack trace indicates, the error happens at line 88 of DirectoryLister.java, in the method enumerateDirectory(). But you have shown us the method getAbsoluteDirectoryPath(). Show us the **relevant** code. The bug is in your code. Not in JFileChooser. – JB Nizet Feb 04 '15 at 21:42
  • Ok, i will post the driver class and supporting class as well. one moment please – JNicholas76 Feb 04 '15 at 21:43
  • The idea is to disable the ability to type a folder name in the gui after clicking the browse button. – JNicholas76 Feb 04 '15 at 21:54
  • That's not a good idea. The good idea would be to fix the bug in your code. What is line 88? – JB Nizet Feb 04 '15 at 21:57
  • from the private void enumerateDirectory(File f) method: for (File file : files) { – JNicholas76 Feb 04 '15 at 22:00
  • You're not showing us the code for that section yet. – Hovercraft Full Of Eels Feb 04 '15 at 22:05
  • 2
    OK. So `files` is null. And it's null because File.listFiles() documentation says: *Returns null if this abstract pathname does not denote a directory, or if an I/O error occurs.* So check that the array returned by listFiles() is not null before iterating. Or at the very least, check that the directory does exist before listing its files. Lesson to learn: don't ignore error messages. They tell you what is wrong. – JB Nizet Feb 04 '15 at 22:07
  • What I was asking is how can I disable the text box so that I can prevent the ability to type the file path and name in the box? The reason I'm going this way is because it would be more logical to not pass anything to the method that is null to begin with, and that is what I'm looking at. Is it possible to disable the ability to send a null pathname by typing it into the browse box? I can see within the documentation that I can enable/disable the file filter dropdown list of the fileChooser, but I'm almost convinced that the text box can't be disabled. – JNicholas76 Feb 04 '15 at 22:20
  • 1
    You're not passing a null path name. You're passing the path of a directory that doesn't exist, or for which there is an exception when listing its files. And that can happen whether or not the file choose allows typing a name. Moreover, if you had to prevent passing null, all you would have to do is `if (path != null)`. – JB Nizet Feb 04 '15 at 22:24

0 Answers0