Java proper use of ArrayList - java

I am currently working on a small project, where a Jframe has a Jlist, which displays an arraylist of files, which have been gathered by scanning through a directory.
The whole process works like this, a seperate class, calls a method in the Jframe class called "main". This "main" method scans through a directory(folderAndFiles) and lists all the file names into a regular text file(file.txt). Aftwerwards the seperate class then displays the Jframe, which then has another scanner, which reads the new text file(file.txt) and turns all the names within that file into an arraylist(filList). Within the initialization function of the Jframe, I am then setting a DefaultListModel to add the arraylist items to the Jlist.
Everything sort of works, but there are some slight hiccups. The first thing is the fact that the Jlist displays the things from the arraylist horizontaly meaning it will be like this [File1.txt, File2.txt, File3.txt, etc...] and not vertically, where the filenames are displayed underneath each other. Then the second issue, which probably would be fixed if the first issue is fixed, the array list is too long and on the Jlist after listing some of the files it ends up saying "line is to long, please switch to wrapped mode to see whole line..."
I am not completely sure whether I am using the arraylist right and why it won't list the items within the Jlist vertically and properly.
The following is the whole Jframe, where the Jlist is placed and the function is happening.
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Scanner;
import javax.swing.DefaultListModel;
public class DisplayTest extends javax.swing.JFrame {
static String username = System.getProperty("user.name");
static File file = new File("file.txt");
static ArrayList<String> filList = new ArrayList<String>();
public DisplayTest(){
initComponents();
DefaultListModel DLM = new DefaultListModel();
DLM.addElement(filList);
jList1.setModel(DLM);
System.out.println(filList);
}
public static void main(String args[]) {
/* Create and display the form */
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new DisplayTest().setVisible(true);
}
});
}
// Variables declaration - do not modify
private javax.swing.JLabel jLabel1;
private javax.swing.JList<String> jList1;
private javax.swing.JScrollPane jScrollPane1;
private javax.swing.JScrollPane jScrollPane2;
private javax.swing.JTextArea jTextArea1;
// End of variables declaration
public static void main() throws IOException {
try {
listFilesForFolderMac(folderAndFiles);
} finally {
Scanner scanner = new Scanner(file);
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
filList.add(line);
}
}
public static void listFilesForFolderMac(final File folder) throws IOException {
PrintWriter writToDoc = new PrintWriter(new FileWriter("file.txt",true));
for (final File fileEntry : folder.listFiles()) {
if (fileEntry.isDirectory()) {
listFilesForFolderMac(fileEntry);
} else {
writToDoc.println(fileEntry.getName());
}
}
writToDoc.close();
}
final static File folderAndFiles = new File("/Users/" + username + "/Documents");
}
The following is how I call the Jframe and function, from the seperate class
public static void main(String[] args) throws IOException {
try {
DisplayTest.main();
} finally {
DisplayTest dTest = new DisplayTest();
dTest.setVisible(true);
}
}

I am not completely sure whether I am using the arraylist right
A JList doesn't know how to display the items in an ArrayList, so you can't just add the ArrayList to the ListModel.
So you need to iterate through the ArrayList and add each item to the ListModel.
Or even easier, just get rid of the ArrayList and read the data from the file directly into the ListModel.
Your code is poorly structured. Any time you see an overuse of static variables and methods you know you have a design problem.
I would start by reading the section from the Swing tutorial on How to Use Lists. There are working examples there that will show you a better program structure. You can start with working code and modify it for your requirements.

Related

Nothing happens when I try to apply an ActionListener to a JButton to change the content of the JLabel

I need a way to create an ActionListener that when a JButton is pressed, it updates the content of 7 different JLabels to display the information in the form of text.
The data is retrieved from methods called from an external JAR file. The methods return ArrayList. I attempted to convert the ArrayList into a String, and tried to change the JLabel content with setText().
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import api.anAPI.THEAPINAME;
public class Controller implements ActionListener {
private MainGUI maingui;
private SubPanel subpanel;
private static THEAPINAME anAPI =new THEAPINAME("XyP0D75oRCGrLE78","x47ka5jmOGaJ2zvw");
static ArrayList<String> nameList =new ArrayList<String>();
private String names;
public Controller(MainGUI maingui,SubPanel subpanel){
this.maingui = maingui;
this.SubPanel = subpanel;
MainGUI.getSearchBtn().addActionListener(this);
nameList.addAll(anAPI.getNames());
for (String s: nameList){
names+= s+"\t";
}
}
public void actionPerformed(ActionEvent e) {
SubPanel.label1.setText(names);
//6 more Labels.
}
}
An additional, because I have 7 JLabels, would I need to do 7 getLabel methods? Or is there a way to get them all with just 1 method.
I am not entirely sure what I am doing incorrectly, it could be that the getMethods I used returned the wrong widget in question as the code for the GUI was not done by me but by a teammate and he had done a really poor job of making it clear for us.
UPDATE:
Fixed up the GUI to make it clearer, so I think that is no longer the problem. Now I think the problem might be that I did not convert the contents of the ArrayList into a String in the way I thought.
The desired function of the code is when the JButton is clicked on, the JLabels in question are all updated to their relevant data.
addController method
public void addController(Controller controller){
control = controller;
jb1.addActionListener(control);
}
You didn't really describe what the problem is of your current code.
You can add a method say getLabels() in SubPanel class to return all of its labels, or you can add a method setLabelText(String text) to set text for all of its labels by extending or directly modifying SubPanel class.
UPDATE
You have several very confusing parts in your code.
In your constructor, it should be this.subpanel = subpanel and then it should be maingui.getSearchBtn().addActionListener(this), also in method actionPerformed it should be subpanel.label1.setText(names). These might not be your problems though since you didn't say it's the code you're actually running.
Looks like that you haven't created any instance of class Controller thus the code in it never gets executed.
You need to have some code outside of you Controller class like this:
MainGUI maingui;
SubPanel subpanel;
// they're somehow initialized
Controller controller = new Controller(maingui, subpanel);

Trivia game with JFrame

I'm trying to make a trivia game. My problem is that, the questions does not show up in the frame when I try to run the program. what should I do? Here's what I have done so far. any help would really be great. thanks in advance.
package trivia;
import java.util.Arrays;
import java.util.List;
public class ChemistryJFrame extends javax.swing.JFrame {
String question, answer;
ChemistryJFrame[] questionbank = new ChemistryJFrame[3];
List<ChemistryJFrame> questionlist = Arrays.asList(questionbank);
int quest;
public ChemistryJFrame() {
initComponents();
}
#SuppressWarnings("unchecked")
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
dispose();
MainJFrame Main = new MainJFrame();
Main.setVisible(true);
}
public static void main(String args[]) {
ChemistryJFrame bank = new ChemistryJFrame();
bank.banklist();
bank.startquiz();
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new ChemistryJFrame().setVisible(true);
}
});
}
public void banklist()
{
questionbank[0] = new ChemistryJFrame();
questionbank[0].question = "Which of the following scientists was awarded the Nobel Prize in 1911 for the discovery of the radioactive elements, radium and polonium?\n A) Charles Darwin\n B) Dmitri Mendeleev\n C) Marie Curie";
questionbank[0].answer = "C";
questionbank[1] = new ChemistryJFrame();
questionbank[1].question = "How many electrons can occupy an s orbital?\n A) one\n B) two\n C) three";
questionbank[1].answer = "B";
questionbank[2] = new ChemistryJFrame();
questionbank[2].question = "Which noble gas has the highest melting point ?\n A) argon\n B) xenon\n C) radon";
questionbank[2].answer = "C";
}
public void startquiz()
{
for(quest=1; quest<10; quest++)
{
questionlabel.setText(questionbank[quest].question);
}
}
// Variables declaration - do not modify
private javax.swing.JButton jButton1;
private javax.swing.JButton jButton2;
private javax.swing.JSeparator jSeparator1;
private javax.swing.JTextField jTextField1;
private javax.swing.JLabel questionlabel;
// End of variables declaration
}
Your start quiz function seems totally wrong to me.
At the moment you are seeing nothing because the quiz start function is very rapidly setting the text to every question - finally ending at question 9 which is blank as you never set it in the banklist function.
I would imagine that you intend to set the text to the qustion[0] text and then wait for some kind of user response?
public void startquiz()
{
for(quest=1; quest<10; quest++)
{
questionlabel.setText(questionbank[quest].question);
}
}
Lots of issues:
You are iterating from 1 to 10, but you only define questionbank as an array of 3 items. ArrayIndexOutOfBounds is being thrown.
Even if the above is solved, you just iterate all questions before the data is even displayed. You would only get to see the last one. Learn to program with listeners, this is how GUIs work (not sequentially as command line programs).
You also have what seems to be an actionListener method for a button that does not exist, clean your code.
You never actually create questionlabel. You need to create it first and then add it to the frame.
Also in this piece of code:
for(quest=1; quest<10; quest++)
{
questionlabel.setText(questionbank[quest].question);
}
You'll be overwriting label text 10 times and only the last question will be shown. What you probably need is ten different labels.
Another thing is that you create only 3 questions, but iterate over 10. Arrays in Java start with zero so you need to change for(quest=1 to for (quest=0
Those are not all of the problems with your code, but keep trying, you'll get there eventually :)

What's wrong with my Dialog box and how should I change arraylist from different class and on separate .java file?

I am trying to write a GUI program that will import a text file, read its content and put them into ArrayList.
I write the panel in a separate .java file that contain the import button and perform the import function, while the Arraylist is on the different .java file (main method ones).
How should I make ActionListener to read and import file contents into ArrayList from different class/.java file?
My import dialog box alos causes error, what's wrong with it? The code works fine in CLI but not in GUI program.
This is the main method of GUI Frame, it will add the panel from different .java file:
public class FrameGUI
{
public static void main(String[] args) throws Exception
{
//Creates ArrayList and initiating JFrame
ArrayList<String> stringFile = new ArrayList<String>();
JFrame frame = new JFrame("Title");
*//Rest of the following codes here*
} //---End of Main Method---
} ---End of the First .java file
This is the second .java file, which contains panel with import button and performing the action, read the contents of .txt file and import them into arraylist:
public class ImportPanel extends JPanel
{
private JButton importButton;
public ImportPanel(ArrayList<String> StringFile)
{
//Setting up JButton and link it to inner class of
//ActionListener
importButton = new JButton("Import Data");
importButton.addActionListener(new importListener());
*//***Adding the button into panel, set background color and panel size*
} //---End of main method---
//Private inner class:
private class importListener implements ActionListener
{
public void actionPerformed (ActionEvent event)
{
//---Import Function---
//The following statement will ask the user for input first
//BEFORE it displays title and JFrame
//Setting the file type, showing the dialog box:
JFileChooser chooser = new JFileChooser();
FileNameExtensionFilter filter = new FileNameExtensionFilter("TEXT FILES",
"txt","text"); //only allows user to import .txt files
chooser.setFileFilter(filter);
int returnVal = chooser.showOpenDialog(null);
//Execute the following and import data
//if the file type match:
Scanner fileScan;
String stringAdd;
if (returnVal == JFileChooser.APPROVE_OPTION) {
File inputFile = chooser.getSelectedFile();
fileScan = new Scanner(inputFile);
//Scan the first line as title:
//-disable-frame = new JFrame (fileScan.nextLine());
//Parsing the data into Arraylist
while (fileScan.hasNext())
{
stringAdd = fileScan.nextLine();
StringFile.add(new String(stringAdd));
} } //End of the if statement-
}
} //---End of private inner class---
} //End of the second .java file
I have tried to search before asking for question, I know that in order to change variable on different class, we need to add something called reference. But I don't know how to add and where to add in this case, when the classes are on two different .java file, rather than one.
In your ImportPanel class how did you use that StringFile ArrayList object in importListener inner class?
Here StringFile is a local object for ImportPanel() constructor. Check this for understanding pass by reference in java. In your case I prefer using a single public static ArrayList<String> StringFile; object in one class and use it in all other classes.

How do I pass the values from one class to another?

I have this gui pop up panel and it got things to filled up like packets number, distance etc. Once users fill in the information, he will click ok, the gui will close and my other gui class which has calculation method should receives all data that are filled in earlier gui. How do I store that data? I know I can store in temp file but I don't want to do that. I hope you can enlighten me.
import java.awt.*;
import java.applet.Applet;
class Example extends Applet implements ActionListener
{
TextField txt = new TextField(10);
Button goButton = new Button("Go");
String data = new String ();
public void init ()
{
add(txt);
add(goButton);
goButton.addActionListener(this);
}
public void actionPerformed (ActionEvent e)
{
String cmd = e.getActionCommand();
if (cmd.equals("Go"))
{
// preserve data
data = txt.getText();
repaint();
}
}
}
You should create an intermediate class that represents the data.
After the GUI has been filled in and the submit button clicked, parse the data and fill in the fields in your class.
For example:
public class MyData {
public String Name;
public String Address;
}
Then, fire a method in your calculation method that takes this class as a parameter:
public void Calculate(MyData data) {
...
}
For more advanced handling, look into "interfaces" in Java - that's the standard way this is done.

Text problems with JPanel

After thinking I was on course to solving a problem with making text (read from a file) appear in a JPanel, I`m frustratingly back to square one.
The code is below. The result is just a blank screen 400x500 screen. Some combinations of using nextLine() + nextLine() as displayText commands result in one word coming up from the file (the word has been different multiple times). This makes me wonder: do I need code that deals with text wrapping? The textfile itself is in paragraphs, and as such, I thought that sf.displayText should say sf.displayText(reader.next() + reader.nextline() + reader.nextline(), and have tried other combinations, but this may be confusing the while parameters. Have also tried a different textfile with simple sentences, no paragraphs, but again, nothing comes up.
Having looked online, I have found that layouts may be an issue, and that alternative options may be BufferedReader or using JTextArea. Browsing through Big Java didn`t provide anything I felt I could take, as all discussion on the scanner went towards integers, whereas the file I want read is prose. I also tried putting a small piece of text in the code itself and cancelling out everything else below it to see if I could transfer text from the code to the JPanel:
StoryFrame sf = new StoryFrame();
sf.displayText("Life is beautiful");
but still nothing came up. Ultimately, I want to put text from a file into a JPanel, and have each paragraph come up 5 seconds after the one before. So ultimately, my questions are:
Why does my text fail to show up, or only display one word? Is it because I don`t specify a layout?
Do I need to think about text wrapping?
Should I look into JTextArea instead of JPanel, and BufferedReader instead of Scanner?
Have I been using the nextLine method from the Scanner correctly?
Can I put a command to read a file and display that file`s text in the display
method of StoryFrame (I think this would make things a lot easier)?
I know it`s a lot, so any answers to any of the questions would be greatly appreciated, thank you.
Tom
import javax.swing.JFrame;
import javax.swing.JLabel;
public class StoryFrame extends JFrame {
private JLabel mylabel;
public StoryFrame() {
setTitle("見張ってしながら...");
setSize(400,500);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLocationRelativeTo(null);
mylabel = new JLabel();
this.add(mylabel);
setVisible(true);
}
public void displayText(String text) {
JLabel storyText = new JLabel();
add(storyText);
}
}
ShowIntro
import java.util.Scanner;
import java.io.File;
import java.io.IOException;
class ShowIntro {
public static void main(String args[])
throws IOException {
StoryFrame sf = new StoryFrame();
Scanner reader = new Scanner(new File("Try.txt"));
while (reader.hasNextLine()) {
//String line = in.nextLine() Not sure whether this would contribute, I doubt it does though
sf.displayText(reader.next());
//sf.displayText(reader.next() + reader.nextLine() + reader.nextLine()); was also attempted.
try {
Thread.sleep(5000);
} catch (InterruptedException e) { }
}
}
}
it fails because you never call a method to use the text in your displaytext method
public void displayText(String text) {
mylabel.setText(text);
}
You are also reading the file one word at a time:
sf.displayText(reader.next());
should be:
sf.displayText(reader.nextLine());
if you want to read upto the next newline character.
Even though this was not in the original question to satisfy some of the comments below here is a modified version of the program
package com.vincentramdhanie.kitchensink;
import java.io.File;
import java.io.IOException;
import java.util.Scanner;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextArea;
public class StoryFrame extends JFrame {
private JTextArea area;
public StoryFrame() {
setTitle("見張ってしながら...");
setSize(400,500);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLocationRelativeTo(null);
area = new JTextArea(10, 30);
area.setEditable(false);
area.setCursor(null);
area.setOpaque(false);
area.setFocusable(false);
this.add(area);
setVisible(true);
}
public void displayText(String text) {
area.setText(text);
}
public static void main(String args[])
throws IOException {
StoryFrame sf = new StoryFrame();
Scanner reader = new Scanner(new File("Try.txt"));
while (reader.hasNextLine()) {
String line = reader.nextLine();
sf.displayText(line);
try {
//to skip blank lines. If the line has no non-space characters then do not sleep
if(!line.trim().equals("")){
Thread.sleep(5000);
}
} catch (InterruptedException e) { }
}
}
}

Categories