Results 1 to 6 of 6
  1. #1
    gkoef is offline Member
    Join Date
    Sep 2010
    Posts
    24
    Rep Power
    0

    Default JFileChooser Problem

    I am busy trying to learn Java using the book Head First Java and I am trying to use JFileChooser so beats can be saved from a music box program (it is in the above book but only uses serialization). Everything compiles OK, even with the added new JFileChooser code, but when I click the 'Save Beat' button, no dialog box appears. The coding is shown below:

    Java Code:
    /*
    	The BeatBox GUI coding
    */
    
    import java.io.*;
    import java.awt.*;
    import javax.swing.*;
    import javax.sound.midi.*;
    import java.util.*;
    import java.awt.event.*;
    
    public class BeatBox
    {
    	JPanel mainPanel;
    	ArrayList<JCheckBox> checkboxList;		//We store checkboxes in an ArrayList
    	Sequencer sequencer;
    	Sequence sequence;
    	Track track;
    	JFrame theFrame;
    
    	String[] instrumentNames = {"Bass Drum", "Closed Hi-Hat", "Open Hi-Hat", "Acoustic Snare", "Crash Cymbal",
    		"Hand Clap", "High Tom", "Hi Bongo", "Maracas", "Whistle", "Low Conga", "Cowbell", "Vibraslap",
    		"Low-mid Tom", "High Agogo", "Open Hi Conga"};								//These are the names of the instruments, as a String array,
    															//for building the GUI labels on each row
    
    	int[] instruments = {35,42,46,38,49,39,50,60,70,72,64,56,58,47,67,63};		//These represent the actual drum 'keys'. The drum channel is like a piano, except each 'key'
    											//on the piano is a different drum. So the number '35' is the key for the Bass drum, 42
    											//is Closed Hi-Hat, etc.
    	public static void main(String[] args)
    	{
    		new BeatBox().buildGUI();
    	}
    
    	public void buildGUI()
    	{
    		theFrame = new JFrame("Cyber BeatBox");
    		theFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    		BorderLayout layout = new BorderLayout();
    		JPanel background = new JPanel(layout);
    		background.setBorder(BorderFactory.createEmptyBorder(10,10,10,10));		//EmptyBorder gives us a margin between the edges of the panel and where the
    												//components are placed. Purely aesthetic.
    
    		checkboxList = new ArrayList<JCheckBox>();
    		Box buttonBox = new Box(BoxLayout.Y_AXIS);					//Create a Box object called buttonBox for a vertical list
    
    		JButton start = new JButton("Start");				//.
    		start.addActionListener(new MyStartListener());			//.
    		buttonBox.add(start);						//.
    										//.
    		JButton stop = new JButton("Stop");				//.
    		stop.addActionListener(new MyStopListener());			//.
    		buttonBox.add(stop);						//.
    										//.
    		JButton upTempo = new JButton("Tempo Up");			//.
    		upTempo.addActionListener(new MyUpTempoListener());		//	These lines of code is GUI set-up code for creating 5 buttons
    		buttonBox.add(upTempo);						//.
    										//.
    		JButton downTempo = new JButton("Tempo Down");			//.
    		downTempo.addActionListener(new MyDownTempoListener());		//.
    		buttonBox.add(downTempo);					//.
    										//.
    		JButton saveBeat = new JButton("Save Beat");			//.
    		downTempo.addActionListener(new OpenChooser());			//.
    		buttonBox.add(saveBeat);					//.
    
    
    		Box nameBox = new Box(BoxLayout.Y_AXIS);
    		for(int i = 0; i < 16; i++)
    		{
    			nameBox.add(new Label(instrumentNames[i]));		//This creates 16 labels with for() loop
    		}
    
    		background.add(BorderLayout.EAST, buttonBox);			//These two lines of code is more GUI set-up code which places the Box objects (buttonBox and
    		background.add(BorderLayout.WEST, nameBox);			//nameBox) where you want them.
    
    		theFrame.getContentPane().add(background);
    
    		GridLayout grid = new GridLayout(16,16);
    		grid.setVgap(1);
    		grid.setHgap(2);
    		mainPanel = new JPanel(grid);
    		background.add(BorderLayout.CENTER, mainPanel);
    
    		for(int i = 0; i < 256; i++)
    		{
    			JCheckBox c = new JCheckBox();				//.
    			c.setSelected(false);					//	Make the checkboxes, set them to false (so they aren't checked) and add them to
    			checkboxList.add(c);					//	the ArrayList AND to the GUI panel.
    			mainPanel.add(c);					//.
    		}
    
    		setUpMidi();
    
    		theFrame.setBounds(50,50,300,300);
    		theFrame.pack();
    		theFrame.setVisible(true);
    	}
    
    	public void setUpMidi()
    	{
    		try
    		{
    			sequencer = MidiSystem.getSequencer();			//.
    			sequencer.open();					//.
    			sequence = new Sequence(Sequence.PPQ,4);		//	Midi set-up for getting the Sequencer, Sequence, and the Track
    			track = sequence.createTrack();				//.
    			sequencer.setTempoInBPM(120);				//.
    		}
    		catch(Exception e)
    		{
    			e.printStackTrace();
    		}
    	}
    
    //The coding from this point is where it all happens! Where we turn the checkbox state into MIDI events, and add them to the Track
    
    
    	public void buildTrackAndStart()
    	{
    		int[] trackList = null;		//We'll make a 16 element array to hold the values of one instrument, across all 16 beats. If the instrument is supposed to
    						//play on that beat, the value of that element will be the key. If the instrument is NOT supposed to play on that beat, put in a zero
    
    		sequence.deleteTrack(track);		//Get rid of the old track,
    		track = sequence.createTrack();		//make a fresh one
    
    		for(int i = 0; i < 16; i++)		//Do this for each of the 16 ROWS (i.e. Bass, Congo etc)
    		{
    			trackList = new int[16];
    
    			int key = instruments[i];		//Set the 'key' that represents which instrument this is. The instruments array holds the actual MIDI numbers
    								//for each instrument
    
    			for(int j = 0; j < 16; j++)		//For each of the BEATS for this row
    			{
    				JCheckBox jc = (JCheckBox) checkboxList.get(j + (16 * i));
    
    				if(jc.isSelected())				//.
    				{						//.
    					trackList[j] = key;			//	Is the checkbox at this beat selected? If yes, put the key value
    				}						//	in this slot in the array (the slot that represents this beat). Otherwise,
    				else						//	the instrument is NOT supposed to play at this beat so set it to zero.
    				{						//.
    					trackList[j] = 0;			//.
    				}						//.
    			}
    
    			makeTracks(trackList);			//For this instrument, and for all 16 beats, make events and add them to the track.
    			track.add(makeEvent(176,1,127,0,16));
    		}
    
    		track.add(makeEvent(192,9,1,0,15));		//We always want to make sure that there IS an event at beat 16 (0 to 15). otherwise the BeatBox might not
    								// go the full 16 beats before it starts over.
    		try
    		{
    			sequencer.setSequence(sequence);
    			sequencer.setLoopCount(sequencer.LOOP_CONTINUOUSLY);		//Lets you specify the number of loop iterations or in this case Continuous looping.
    			sequencer.start();
    			sequencer.setTempoInBPM(120);
    		}
    		catch(Exception e)
    		{
    			e.printStackTrace();
    		}
    	}
    
    	public class MyStartListener implements ActionListener			//.
    	{									//.
    		public void actionPerformed(ActionEvent a)			//.
    		{								//	First of the inner classes (listener for Start button)
    			buildTrackAndStart();					//.
    		}								//.
    	}									//.
    
    	public class MyStopListener implements ActionListener
    	{
    		public void actionPerformed(ActionEvent a)
    		{
    			sequencer.stop();
    		}
    	}
    			
    	public class MyUpTempoListener implements ActionListener
    	{
    		public void actionPerformed(ActionEvent a)
    		{
    			float tempoFactor = sequencer.getTempoFactor();
    			sequencer.setTempoFactor((float)(tempoFactor * 1.03));		//Default is 1.0 so this increases the default by 3% per click
    		}
    	}
    
    	public class MyDownTempoListener implements ActionListener
    	{
    		public void actionPerformed(ActionEvent a)
    		{
    			float tempoFactor = sequencer.getTempoFactor();
    			sequencer.setTempoFactor((float)(tempoFactor * .97));		//Default is 1.0 so this decreases the default by 3% per click
    		}
    	}
    
    //START OF EDIT
    
    	public class OpenChooser implements ActionListener		//this class is created so a pattern of beats can be saved
    	{
    		public void actionPerformed(ActionEvent a)		//User clicks button and the ActionEvent fires
    		{
    			JFileChooser saveIt = new JFileChooser();	//Hopefully brings up a dialog box
    			saveIt.showSaveDialog(theFrame);		//and waits for the user to click 'Save'
    			saveFile(saveIt.getSelectedFile());		//from the dialog box
    		}
    	}
    
    	private void saveFile(File file)				//Hopefully this method() will write out the file and save it
    	{
    		boolean[] checkboxState = new boolean[256];		//Make a boolean array to hold the state of each checkbox (may work)
    
    		for(int i = 0; i < 256; i++)
    		{
    			JCheckBox check = (JCheckBox) checkboxList.get(i);		//.		
    			if(check.isSelected())						//.						
    			{								//	Walk through the checkboxList (ArrayList of checkboxes and get the state
    					checkboxState[i] = true;				//	of each one and add it to the boolean array
    			}								//.
    		}
    		//End of may work
    		try
    		{
    			BufferedWriter writer = new BufferedWriter(new FileWriter(file));
    			writer.close();
    		}
    		catch(IOException ex)
    		{
    			System.out.println("Cannot Save file");
    			ex.printStackTrace();
    		}
    	}
    //END OF EDIT
    
    	public void makeTracks(int[] list)		//This makes events for one instrument at a time for all 16 beats. So, it might get an int[] for the Bass drum,
    	{						//and each index in the array will hold either the key for that instrument, or a zero. If it's a zero, the instrument isn't
    							//supposed to play at that beat. Otherwise, make an event and add it to the track.
    		for(int i = 0; i < 16; i++)
    		{
    			int key = list[i];
    
    			if(key != 0)
    			{
    				track.add(makeEvent(144,9,key, 100, i));		//Make the NOTE ON and NOTE OFF events,
    				track.add(makeEvent(128,9,key, 100, i+1));		//and add them to the Track
    			}
    		}
    	}
    
    	public MidiEvent makeEvent(int comd, int chan, int one, int two, int tick)
    	{
    		MidiEvent event = null;
    		try
    		{
    			ShortMessage a = new ShortMessage();
    			a.setMessage(comd, chan, one, two);
    			event = new MidiEvent(a, tick);
    		}
    		catch(Exception e)
    		{
    			e.printStackTrace();
    		}
    		return event;
    	}
    }

  2. #2
    dlorde is offline Senior Member
    Join Date
    Jun 2008
    Posts
    339
    Rep Power
    7

    Default

    You're adding the file chooser action listener to downTempo instead of saveBeat. A copy/paste error?

  3. #3
    gkoef is offline Member
    Join Date
    Sep 2010
    Posts
    24
    Rep Power
    0

    Default

    Thank you.:)

    That was worked out quick. Is there a way of checking mistakes like this without scouring every character in the coding?

  4. #4
    DarrylBurke's Avatar
    DarrylBurke is offline Member
    Join Date
    Sep 2008
    Location
    Madgaon, Goa, India
    Posts
    11,193
    Rep Power
    19

    Default

    Yes, there is. Test functionality at every step as you write your code. That way, you know any problem you encounter is likely to be in the last bit of code you added.

    db

  5. #5
    dlorde is offline Senior Member
    Join Date
    Jun 2008
    Posts
    339
    Rep Power
    7

    Default

    These things happen however careful you think you are. Debugging is the art of working out what's gone wrong and where. Java error messages & exceptions generally tell you the basic what and where, but if you don't get any errors you need to take a logical, stepwise approach to identify what the problem is and where it is happening. Like many things in life, it becomes quicker and easier with experience.

    If you push a button and nothing happens, the obvious place to look is the ActionListener for the button. It's one of those things that's easy to forget to add or implement.

    Try googling for "java debugging techniques" for detailed debugging help.

  6. #6
    dlorde is offline Senior Member
    Join Date
    Jun 2008
    Posts
    339
    Rep Power
    7

    Default

    Quote Originally Posted by Darryl.Burke View Post
    Test functionality at every step as you write your code. That way, you know any problem you encounter is likely to be in the last bit of code you added.
    Good point.

    Time spent learning how to use a unit testing tool like JUnit or TestNG can repay itself 100-fold.

    Test-first and test-driven development are interesting techniques/philosophies - I never had the patience to go the whole hog, and they're no substitute for preparatory design work, but the principles are seductive.

Similar Threads

  1. Problem with saving from JFileChooser
    By fireshadow4126 in forum AWT / Swing
    Replies: 2
    Last Post: 11-24-2010, 08:21 PM
  2. Problem with JFileChooser and BufferedImage Class
    By toro1984 in forum AWT / Swing
    Replies: 3
    Last Post: 11-03-2010, 10:09 AM
  3. JFileChooser problem
    By jperson in forum New To Java
    Replies: 2
    Last Post: 02-06-2010, 07:31 PM
  4. jfilechooser and jtextarea problem
    By kostinio in forum AWT / Swing
    Replies: 7
    Last Post: 10-07-2009, 08:46 AM
  5. JFileChooser horizontal scrollbar problem
    By nenadm in forum AWT / Swing
    Replies: 4
    Last Post: 11-12-2008, 11:16 AM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •