I got some really good responses here last time, which really helped out quite a bit, so I thought I'd try again with a new batch.
Below is the second phase of my first Java project: Intercommunication between panels. This builds upon the old code, though it has been heavily modified since the first version. Many of the suggestions from the previous question have been implemented and a lot of new code and features have been added. In fact most of this is new code and does not concern the previous question. I only mention this in case you helped in the previous question or were curious. You may view the previous question if you need more context. As before, specific questions and comments are located below the code.
JFileParser.java(main)
package my;
import my.controllers.Logger;
import my.views.Deck;
import my.controllers.DeckNavigator;
import javax.swing.JFrame;
import java.awt.BorderLayout;
import javax.swing.SwingUtilities;
public class JFileParser implements Runnable {
public static void main( String[] args ) {
SwingUtilities.invokeLater( new JFileParser() );
}
@Override
public void run() {
JFrame frame = new JFrame( "Java File Parser" );
Deck deck = new Deck();
DeckNavigator navigator = new DeckNavigator();
navigator.setDeck( deck );
deck.setNavigator( navigator );
deck.initDeck();
frame.getContentPane().add( deck, BorderLayout.NORTH );
frame.getContentPane().add( navigator, BorderLayout.SOUTH );
frame.pack();
frame.setLocationRelativeTo( null );
frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
frame.setVisible( true );
}
}
Deck.java
package my.views;
import my.controllers.DeckNavigator;
import javax.swing.JPanel;
import java.awt.CardLayout;
import java.util.List;
import java.util.Arrays;
public class Deck extends JPanel {
private CardLayout layout;
private DeckNavigator navigator;
private static final String
EMPTY_PANEL = "New window",
FILE_CHOOSER = "File chooser",
FILE_PARSER = "File parser"
;
private List< String > deck = Arrays.asList(
EMPTY_PANEL,
FILE_CHOOSER,
FILE_PARSER
);
public Deck() {
setLayout( new CardLayout() );
layout = ( CardLayout ) getLayout();
}
public void setNavigator( DeckNavigator navigator ) {
this.navigator = navigator;
}
public void initDeck() {
add( new JPanel(), EMPTY_PANEL );
add( new ChooseFile(), FILE_CHOOSER );
add( new ParseFile(), FILE_PARSER );
navigator.setView( EMPTY_PANEL );
}
public void nextView( String view ) {
int currentView = deck.indexOf( view );
if( currentView != deck.size() - 1 ) {
setView( currentView + 1 );
}
}
public void previousView( String view ) {
int currentView = deck.indexOf( view );
if( currentView > 0 ) {
setView( currentView - 1 );
}
}
private void setView( int card ) {
String view = deck.get( card );
layout.show( this, view );
navigator.setView( view );
}
}
DeckNavigator.java
package my.controllers;
import my.views.Deck;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JPanel;
public class DeckNavigator extends JPanel {
private Deck deck;
private String view;
public DeckNavigator() {
addPrevious();
addNext();
}
public void setDeck( Deck deck ) {
this.deck = deck;
}
public void setView( String view ) {
this.view = view;
}
private boolean deckIsSet() {
return deck != null;
}
private boolean viewIsSet() {
return view != null;
}
private void addPrevious() {
JButton button = new JButton( "Back" );
button.addActionListener( new ActionListener() {
@Override
public void actionPerformed( ActionEvent e ) {
if( deckIsSet() && viewIsSet() ) {
deck.previousView( view );
}
}
} );
add( button );
}
private void addNext() {
JButton button = new JButton( "Next" );
button.addActionListener( new ActionListener() {
@Override
public void actionPerformed( ActionEvent e ) {
if( deckIsSet() && viewIsSet() ) {
deck.nextView( view );
}
}
} );
add( button );
}
}
Notes:
- My packages aren't that vague, I just abstracted them before posting this.
- The logger is a pseudo class. All it does is print to the console for now. Though I'm not using it as much now...
- My first panel is blank to simulate the need to click on the appropriate menu item
Questions
- When using the
invokeLater()
method in my main class, would it be better, or possible to usethis
instead of getting a new instance of the same class? I just thought of this, so I haven't even tried it or looked it up yet. Edit: Just tested this, appears it doesn't work becausethis
is not static, worth a shot. - After many hours on google, and very little sleep, the only way I could think to get my panels to communicate with each other was to do as you've just seen. And I didn't come up with that solution until after I did get some sleep. I say only because I don't think writing to a temp file is a very elegant solution in this instance. Is there a better way to do this? Already I'm seeing issues when I want another class to be able to change the view, and I'd hate to have to pass the deck and navigator to every panel on the off chance they or their children will need it at some point. I know I can streamline it by extending a parent class with those methods, but just curious what y'all have to say.
- Is there a better way to navigate and/or store the deck? I initially thought of combining the "titles" and panels into an associative array, or HashMap as I've come to know they're called in Java, that way I could iterate over it to initialize the deck instead of having to explicitly call each panel. But that immediately presented problems when I tried to navigate sequentially through them as I couldn't get their position with
indexOf()
. I thought of creating an iterator for it, but, I admit, I'm not very familiar with the concept and didn't see a "previous" method available in the interface, which makes me think I would have to create a completely different iterator and deck but backwards if I wanted to step down.
Please feel free to elaborate on other points than just those I listed. I'm still trying to learn, so any help is appreciated.