This is my current menu :
public class DrawPolygons
{
public static void main (String[] args) throws FileNotFoundException
{
/**
* Menu - file reader option
*/
JMenuBar menuBar;
JMenu menu;
JMenuItem menuItem;
// Create the menu bar.
menuBar = new JMenuBar();
// Build the first menu.
menu = new JMenu("File");
menu.setMnemonic(KeyEvent.VK_F);
menu.getAccessibleContext().setAccessibleDescription("I have items");
menuBar.add(menu);
// a group of JMenuItems
menuItem = new JMenuItem("Load",KeyEvent.VK_T);
menuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_1, ActionEvent.ALT_MASK));
menuItem.getAccessibleContext().setAccessibleDescription("Load your old polygons");
menu.add(menuItem);
menuItem = new JMenuItem("Save",KeyEvent.VK_U);
menuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_2, ActionEvent.ALT_MASK));
menuItem.getAccessibleContext().setAccessibleDescription("Save the contents of your polygons");
menu.add(menuItem);
// attaching the menu to the frame
JFrame frame = new JFrame("Draw polygons");
frame.setJMenuBar(menuBar);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setContentPane(new DrawingPanel());
frame.pack();
frame.setVisible(true);
}
}
It has two options for Load
and Save
.
Now , how can I attach the JFileChooser
to the actionPerformed
method , here :
/**
* Main class
* @author X2
*
*/
class DrawingPanel extends JPanel implements MouseListener, MouseMotionListener ,KeyListener
{
// code
// code
// and more code
static DrawingPanel app ;
private static final Dimension MIN_DIM = new Dimension(300, 300);
private static final Dimension PREF_DIM = new Dimension(500, 500);
public Dimension getMinimumSize() { return MIN_DIM; }
public Dimension getPreferredSize() { return PREF_DIM; }
JMenuItem open, save;
JTextArea textArea ;
JFileChooser chooser ;
FileInputStream fis ;
BufferedReader br ;
FileOutputStream fos ;
BufferedWriter bwriter ;
public void actionPerformed( ActionEvent event )
{
Object obj = event.getSource() ;
chooser = new JFileChooser() ;
if ( chooser.showOpenDialog( app ) == JFileChooser.APPROVE_OPTION )
if ( obj == open )
{
try
{
fis = new FileInputStream(
chooser.getSelectedFile() ) ;
br = new BufferedReader(
new InputStreamReader( fis ) ) ;
String read ;
StringBuffer text = new StringBuffer() ;
while( ( read = br.readLine() ) != null )
{
text.append( read ).append( "\n" ) ;
}
textArea.setText( text.toString() ) ;
}
catch( IOException e )
{
JOptionPane.showMessageDialog( this , "Error in File Operation"
,"Error in File Operation" ,JOptionPane.INFORMATION_MESSAGE) ;
}
}
}
/**
* The constructor
*/
DrawingPanel()
{
super();
addMouseListener(this);
addMouseMotionListener(this);
addKeyListener(this);
setFocusable(true);
requestFocusInWindow();
}
// a lot of code more
// and more
// and more
}
With the initial code of the menu
and the Jpanel
, that I created in main
?
Regards
------------------------
EDIT:
The "new" code :
public class DrawPolygons
{
public static void main (String[] args) throws FileNotFoundException
{
// attaching the menu to the frame
JFrame frame = new JFrame("Draw polygons");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// JMenuBar
// Create the menu and JmenuBar
JMenuBar menuBar = new JMenuBar();
// Build the first menu.
JMenu menu = new JMenu("File");
menu.setMnemonic(KeyEvent.VK_F);
menu.getAccessibleContext().setAccessibleDescription("I have items");
menuBar.add(menu);
// menu option - load
// create the load option
final JMenuItem loadItem = new JMenuItem("Load",KeyEvent.VK_T);
// add the shortcut
loadItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_1, ActionEvent.ALT_MASK));
// short description
loadItem.getAccessibleContext().setAccessibleDescription("Load your old polygons");
// JFileChooser with filter
JFileChooser fileChooser = new JFileChooser(".");
// apply the filter to file chooser
FileNameExtensionFilter filter = new FileNameExtensionFilter("scn files (*.scn)", "scn");
fileChooser.setFileFilter(filter);
fileChooser.setControlButtonsAreShown(false);
frame.add(fileChooser, BorderLayout.CENTER);
final JLabel directoryLabel = new JLabel(" ");
directoryLabel.setFont(new Font("Serif", Font.BOLD | Font.ITALIC, 36));
final JLabel filenameLabel = new JLabel(" ");
filenameLabel.setFont(new Font("Serif", Font.BOLD | Font.ITALIC, 36));
// add listener to LOAD
loadItem.addActionListener(
new ActionListener()
{
public void actionPerformed(ActionEvent actionEvent)
{
JFileChooser theFileChooser = new JFileChooser();
String command = actionEvent.getActionCommand();
if (command.equals(JFileChooser.APPROVE_SELECTION)) {
File selectedFile = theFileChooser.getSelectedFile();
directoryLabel.setText(selectedFile.getParent());
filenameLabel.setText(selectedFile.getName());
} else if (command.equals(JFileChooser.CANCEL_SELECTION)) {
directoryLabel.setText(" ");
filenameLabel.setText(" ");
}
}} // end listener
); // end listener to loadItem
menu.add(loadItem);
// now SAVE
// create the option for save
JMenuItem saveItem = new JMenuItem("Save",KeyEvent.VK_U);
// key shortcut for save
saveItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_2, ActionEvent.ALT_MASK));
saveItem.getAccessibleContext().setAccessibleDescription("Save the contents of your polygons");
// add the save to the menu
menu.add(saveItem);
frame.setJMenuBar(menuBar);
frame.setContentPane(new DrawingPanel());
frame.pack();
frame.setVisible(true);
}
}
The problem is , now , when I hit Load
Under File
, nothing is happening . Why ?
I added the listener , but nothing .
The quick-fix for your problem is to provide a handler so that you can attach the ActionListener. You make the JMenus in
main()
, but you don't have visibility to them in yourDrawingPanel
. A cheap way to get this done would be to pass the JMenuItems into your DrawingPanel constructor. Modify the constructor to something like:Then you'd pass them into your DrawingPanel in
main
:From a Java-style perspective, it's not clear whether
DrawingPanel
is the best place to handle save and load actions. As others have mentioned, creating (separate) Actions for each JMenuItem is often a better pattern. In your case, you might be able to provide other accessor or helper methods inside DrawingPanel that would give the saver/loader workers the info they'd need to do their Action.Edit: (to address the OP's "new code" Edit)
I think the problem with the "new code" is that you're making a
new
JFileChooser in theactionPerformed
method, and not using the existing one that you made earlier and added to the frame. If you make the first onefinal
then you can use the same JFileChooser in theactionPerformed
method.To elaborate on what Kitesurfer said I would use an Action because most often I have toolbar buttons or other components performing the same actions as menu items. To avoid duplicate or unnecessary code somewhere in the class (or any where I'm able to access it from the current class) I create an
Action
field that I can reuse if need be or move if I decide to refactor my code. Here's an example.Definitely check out the API to see what parameters can be passed into the
AbstractAction
class, I used aString
so theJMenuItem
would display the string, you can also set theIcon
, I don't remember all of the constructors so it would be worth taking a look. Oh and passing theJMenuItems
into the constructor of theDrawingPanel
class isn't necessarily a bad idea, but if it inherits fromJPanel
I don't believe you can add a menu bar to aJPanel
so make sure it gets added to yourJFrame
too. Hope that helps.As a general rule, you should not have your GUI classes, such as the class extending JPanel, implement any listener interfaces, and in fact you should strive for just the opposite -- to separate the control functions of the program (the listeners and the like) from the view functions of the program (the GUI). So my answer to your question of "how can I attach the JFileChooser to the actionPerformed method... [to my DrawingPanel class which extends JPanel], is to strive to not do this.
Instead have your view classes implement interfaces that would allow the control classes to more easily interact with them.
Edit 1: your new code you never display the JFileChooser dialog. You need to display the open dialog:
Edit 2
Swing Model-View-Control Example:
For example, here's an MVC or Model-View-Control implementation that shows the view, the model and the control. This is all very simplistic, and all it does at present is to open a text file and display it in a JTextField, that's it, and it tries to seperate out the control functions from the view.
MvcMain class
MvcModel interface
MvcView interface
ShowTextView class
ShowTextModel class
ShowTextControl class
In this example, I've combined java classes in one file for brevity, but in the application, they'd be in their own files but would all share the same package. Note that while this may be "over-kill" for this simple application, I've used this sort of structure with several very large Swing applications with good success. The main benefit for me comes when I need to debug or enhance a program months after creation, since this separation of concerns and information and behavior hading makes it much easier for me make changes in one part of the program without offending or upsetting another part of the program.
Also, the reason for the interfaces is so that you can create new or different GUI's that look differently, but that can respond in the same way. I've also used them frequently to help create mock classes that allow me to better test my modules in isolation.
I would recommend using Action(s) to use there. On each action you have some specific actionlistener, set your panel as an listener if you like to do so:
Action Explained