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);
}
}