This is my second "first" attempt at starting Java. My first was cut short when I had to go back to a PHP project that required my immediate attention. But perhaps that was a good thing. I learned quite a bit more about OOP, better coding practices, and some other topics. So, after this hiatus, I noticed quite a bit wrong with my first attempt and ended up scraping it and starting from scratch.
So here is the first phase of my Java Project: The Second "First" Attempt. Sounds like a horrible sequel to a horrible movie. The project, once complete, will convert a text file to a CSV file. The format is custom, so it is unlikely that preexisting libraries will help me here, so I didn't even bother looking, except for guidelines on how to go about it. This first class is relatively simple and creates a window with some instructions on how to use the program and a button that allows the user to begin the process by loading a text file. Not very exciting yet, but that's why its only the first phase. Please take a look at it and let me know how you think this can be improved.
I have some specific questions and concerns, located below the code, however there are a number of them and they are quite lengthy. So if you just wish to review the code and skip the questions, that's fine too.
package view;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JLabel;
import javax.swing.JButton;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFileChooser;
import javax.swing.filechooser.FileFilter;
import javax.swing.filechooser.FileNameExtensionFilter;
public class JavaFileParser extends JFrame implements ActionListener {
/*------------------------------------------------------------------------------
CONSTRUCT
------------------------------------------------------------------------------*/
public static void main( String[] args ) {
JavaFileParser parser = new JavaFileParser();
parser.pack();
parser.setVisible( true );
}
public JavaFileParser() {
System.out.println( "Generating user interface..." );
this.setTitle( "Title" );
this.setLocationRelativeTo( null );
this.setDefaultCloseOperation( EXIT_ON_CLOSE );
JPanel panel = addPanel();
JLabel label = addLabel( "Contents" );
panel.add( label );
JButton button = addButton( "Open File", "Open a file to begin..." );
panel.add( button );
}
/*------------------------------------------------------------------------------
PUBLIC METHODS
------------------------------------------------------------------------------*/
public JPanel addPanel() {
System.out.println( "Generating frame panel..." );
JPanel panel = new JPanel();
this.getContentPane().add( panel );
panel.setLayout( new FlowLayout() );
return panel;
}
public JLabel addLabel( String text ) {
System.out.println( "Generating label with the following contents: " + text );
return new JLabel( text );
}
public JButton addButton( String title, String tooltip ) {
System.out.println( "Generating button with the value of: " + title );
JButton button = new JButton( title );
System.out.println( "Generating tooltip for button \"" + title + "\" with a value of: " + tooltip );
button.setToolTipText( tooltip );
button.addActionListener( this );
return button;
}
public void actionPerformed( ActionEvent e ) {
System.out.println( "Generating File Chooser Dialog..." );
JFileChooser filechooser = new JFileChooser();
FileFilter filter = new FileNameExtensionFilter( "Text Files", "txt" );
filechooser.addChoosableFileFilter( filter );
filechooser.setFileFilter( filter );
int returnValue = filechooser.showDialog( this, "Open Report" );
if( returnValue == JFileChooser.APPROVE_OPTION ) {
System.out.println( "class and method not yet implemented" );
}
}
}
Some Specific Questions and Concerns
You might have noticed the package name is "view". Having just spent a considerable amount of time with MVC, I figured I would see if I couldn't use that design pattern here. However, I don't know how well the PHP version I'm familiar with translates to Java. It feels like there is just too much application logic in here for a view, however, at the same time, this all feels necessary to render it. Is this the proper way to go about it? Is there a similar design pattern or one better suited for this application?
This list of imports seems rather long. It feels like I may have too many dependencies, but I am lost as to how I could separate them, or if its even necessary.
I've seen a number of places say that it is not a good idea to extend common libraries, such as JFrame. Their reasoning being that JFrame is simply too heavy and methods are too easy to override by accident. On that same token, I've seen some people express that it is ok to extend JFrame if your application IS a JFrame. I wrote this program before reading these posts so I decided to leave it and see what you all think. Does this also apply to implementing common libraries, such as what I'm doing with ActionListener?
Normally I would name files/classes based on their purpose. So in this instance, I would want to call this file/class "main" or "index" to indicate this is the first "page" the user will arrive on. However, as this is also first class of the program, it is named after the program. Should I separate this to a "main" or "index" file/class and import it in this current file/class?
import view.index; public class JavaFileParser { public static void main( String[] args ) { index index = new index(); index.pack(); index.setVisible( true ); } }
Because this class extends JFrame I can use those methods inherited from it without needing to reference an instance. I found this uncomfortable. Having come from PHP I was so used to doing
$this->method()
that I kept finding myself thinking and then typing$this
before stopping myself. That was until I found a post where the author usedthis.method()
. I adopted it and haven't had an issue since. What are the pro's and con's of this? Are there any, or is this just a style preference? Am I practicing a bad habit?Is it considered bad practice to leave
println()
s in the code? I find it very convenient during debugging to see the progress of the program, but is it something I should remove from the program when it is done? Does it matter? I was actually thinking of eventually converting them to logging methods so that I could easily get log dumps if any errors occured, is this the traditional way this is done, or is there some better way?I originally was not implementing the ActionListener class and was using a lamda function in the
addActionListener()
method called within theaddButton()
method. I didn't like how bulky it made my code, nor am I too terribly impressed with lamda functions in general. I can foresee reasons why I might need to implement lamda functions in Java in the future, say i need multiple action listeners, but is this implementation ok here?