Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

The purpose of this assignment is to use threads to separate a long running proc

ID: 642191 • Letter: T

Question

The purpose of this assignment is to use threads to separate a long running process from the event dispatch thread. You will use a JFileChooser to select one or more text files from your local file system. Display these files (including the path) in a JList. After the user is finished adding files the application will count the vowels in each file and display the results for each file in a second JList.

1.Your application (the class with the main method) must be named VowelCounterApp.java. You may use more classes if desired.

2. Create a user interface with a button that when clicked displays a JFileChooser. If the user selects a text file, display the file name, including the path, in a JList. Allow the user to click this button and add as many files as desired. Filter the file dialog so only folders and .txt files are displayed. Properly handle the situation where the user cancels the JFileChooser. Review the material in the textbook if you are unfamiliar with the  JFileChooser class.

3. Include a button that when clicked processes the selected text files from the JList. Processing requires each file to be read and the vowels counted. This work must be done in a separate thread. Process each file in a different thread. This means a thread separate from the event dispatch thread and separate from the main processing thread.

4. Include a "clear" button that will return the application to its beginning state. "Beginning state" means as if the application had been restarted.

5. Display the file name and the number of vowels in a second JList. The order the files appear in the second JList doesn't have to match the order of the files in the first JList.

6. Add a JScrollPane to each JList so scroll bars appear as necessary.

7. Process only text files. Review the material in the textbook or the prerequisite course if you are unsure how to read a text file. To really test this application you need to either process a great many files at one time or you need a smaller number of really big text files. You can find some large text files by searching the Internet for "large text files".

8. Provide a button that when click displays a dialog with "help" information that explains how the application works.

Explanation / Answer

import javax.swing.*;
import javax.swing.border.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.text.*;

class CountWords {
public static void main(String[] args) {
JFrame.setDefaultLookAndFeelDecorated(true);
JFrame frame = new WordsFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}

class WordsFrame extends JFrame {
WordsPanel panel;
  
//create a frame and a panel
public WordsFrame() {
setTitle("Words, vowels and spaces");
panel = new WordsPanel();
  
/**
The first component in the frame that has focus is
JCheckBox: words. We need to move the focus to JTextArea,
so we make sure 'area' in JPanel gets the focus
whenever a frame is activated.
This is a work-around solution, a simple call to
requestFocusInWindow() on text area should work, but it didn't!
*/
addWindowListener(new WindowAdapter() {
public void windowActivated(WindowEvent e) {
panel.area.requestFocusInWindow();
}
});

//add this panel to the frame
add(panel);
pack();
}
}

//words, vows and spaces panel
class WordsPanel extends JPanel implements ActionListener {
JPanel cbPanel; //panel for check boxes
JPanel tfPanel; //panel for text fields
JPanel btPanel; //panel for buttons
JPanel leftPanel; //panel for panels above
JCheckBox words; //word count check box
JCheckBox vowels; //vow count check box
JCheckBox spaces; //space count check box
JButton ok; //ok button
JButton exit; //exit button
JTextArea area; //area for input
JTextField wdCount; //text field for words
JTextField vwCount; //text field for vows
JTextField spCount; //text field for spaces
Font font = new Font("Serif", Font.BOLD, 12);
  
public WordsPanel() {
setLayout(new FlowLayout());
  
//JCheckBox in a panel
words = new JCheckBox("Words");
words.addActionListener(this);
vowels = new JCheckBox("Vowels");
vowels.addActionListener(this);
spaces = new JCheckBox("Spaces");
spaces.addActionListener(this);
cbPanel = new JPanel(new GridLayout(3, 1));
cbPanel.add(words);
cbPanel.add(vowels);
cbPanel.add(spaces);
  
//JTextFields in a panel
wdCount = new JTextField(8);
wdCount.setEditable(false);
wdCount.setFont(font);
wdCount.setHorizontalAlignment(JTextField.CENTER);
vwCount = new JTextField(8);
vwCount.setEditable(false);
vwCount.setFont(font);
vwCount.setHorizontalAlignment(JTextField.CENTER);
spCount = new JTextField(8);
spCount.setEditable(false);
spCount.setFont(font);
spCount.setHorizontalAlignment(JTextField.CENTER);
tfPanel = new JPanel(new GridLayout(3, 1, 2, 2));
tfPanel.add(wdCount);
tfPanel.add(vwCount);
tfPanel.add(spCount);
  
//ok and exit buttons in their panel
ok = new JButton("OK");
ok.addActionListener(this);
exit = new JButton("EXIT");
exit.addActionListener(this);
btPanel = new JPanel(new GridLayout(1, 2, 2, 2));
btPanel.setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createLineBorder(Color.LIGHT_GRAY),
BorderFactory.createEmptyBorder(4, 4, 4, 4)
));
btPanel.add(ok);
btPanel.add(exit);
  
//panel contains JCheckBox panel,
//JTextField panel and JButton panel
leftPanel = new JPanel(new BorderLayout());
leftPanel.setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createLineBorder(Color.LIGHT_GRAY),
BorderFactory.createEmptyBorder(2, 2, 2, 2)
));
leftPanel.add(cbPanel, BorderLayout.WEST);
leftPanel.add(tfPanel, BorderLayout.EAST);
leftPanel.add(btPanel, BorderLayout.SOUTH);
  
//area where input is entered
area = new JTextArea(7, 20);
area.setText("Enter your sentences here.");
/**
highlights the default text and
wraps each word in the area.
*/
area.selectAll();
area.setLineWrap(true);
area.setWrapStyleWord(true);
  
//add area to scroll pane to get auto-activate scroll bar
JScrollPane scrollPane = new JScrollPane(area);
  
//add components to the main panel
add(leftPanel);
add(scrollPane);
}
  
//performs action
public void actionPerformed(ActionEvent e) {
//gets sentences from JTextArea
String list = area.getText();
//array to store each count
int[] counts = new int[3];
//calls getAllCounts() to process the list.
counts = getAllCounts(list);
  
//OK button is clicked
if(e.getSource() == ok) {
//words check box
if(words.isSelected())
wdCount.setText("" + counts[0]);
else
wdCount.setText("");
  
//vows check box
if(vowels.isSelected())
vwCount.setText("" + counts[1]);
else
vwCount.setText("");
  
//spaces check box
if(spaces.isSelected())
spCount.setText("" + counts[2]);
else
spCount.setText("");
}
  
//EXIT button is clicked
if(e.getSource() == exit) {
int status = JOptionPane.showConfirmDialog(null, "Are you sure?");
if(status == JOptionPane.OK_OPTION)
System.exit(0);
}
}
  
//counts words, vows and spaces
private int[] getAllCounts(String list) {
/**
counted[0] = words,
counted[1] = vows,
counted[2] = spaces.
*/
int[] counted = new int[3];
  
boolean preWhite = true; //white space ahead of a word
int index = 0;
  
//loops through each character in the string
while(index < list.length()) {
char ch = list.charAt(index++);
boolean curWhite = Character.isWhitespace(ch);
/**
only when we found a white space after
each word, this statement is true.
*/
if(preWhite && !curWhite)
counted[0]++;
preWhite = curWhite;
  
if(curWhite)
counted[2]++;
  
ch = Character.toLowerCase(ch);
if(ch == 'a' || ch == 'e' || ch == 'i' ||
ch == 'o' || ch == 'u')
counted[1]++;
}
return counted;
}
}