If anyone can throw a good suggestion my way, i 'd love it.

I'm coding a piano that uses Swing and the piano keys are JButtons. A standard computer keyboard can be used to play notes by linking up to the JButtons. I'm only using two buttons for a prototype. So far I've implemented my key listeners and properly and when I hit 'c' on my keyboard, the responding JButton lights up and the MIDI note plays. But to use to the other button, I have to 'TAB' across before the same thinig will work with 'd'.

As far as I can tell, its something to do with requestFocus or setFocus, or something like that. I'm not to up on Focus Management and I just can't get my head around it.

Any help would be great.
Thanks.

Recommended Answers

All 4 Replies

Are you using the KeyListener or the ActionListener? If you want the input to be from the keyboard then I wouldn't use JButtons.

I'm using ActionListener to handle mouse clicks.
Input from the keyboard is using KeyListener.
It all works.
But my question is concerned with focus.

// Class for CButton.
	    public class CButton implements ActionListener, KeyListener
	    {
		// Create instance of class.
		MidiSynthesizer midisynthesizer = new MidiSynthesizer();

		// Method to pass relevant note to the MidiSynthesizer class.
		public void doIT()
		{	
			// Set the index of the note associated with this button.
           
			int playnote = midisynthesizer.notes[12];
			// Send index to array of notes to play.
			midisynthesizer.playIt(playnote);
		}
		
		// Method to perform an action when the button is interacted with.
		public void actionPerformed(ActionEvent e)
		
		{
			// Call the doIT method.
			doIT();
	   
		}
		
		// Invoked when a key has been typed.
		public void keyTyped(KeyEvent e)
		{
			
		}
		
		// Invoked when a key has been pressed.
		public void keyPressed(KeyEvent e)
		{
			// Returns the integer code for the key on the keyboard and if keyCode is equal to VK_C (ASCII C)... 
			if(e.getKeyCode() == KeyEvent.VK_C)
			{
				// ...call the doIT method.
				doIT();
			}
		}
		
		// Invoked when a key has been released.
		public void keyReleased(KeyEvent e)
		{
			
		}
	}

Sorry about that being so long. Essentially, I want to sit here and type 'c', 'd', 'c', 'd'... etc. And it'll play the MIDI files associated. The only problem is, I have to hit 'TAB' to switch the focus from one JButton to the other.

You don't show how you are attaching the listeners, but yes, it's a focus issue. The easiest thing for you to do is define the actions for those listeners as small inner classes that extend AbstractAction. That will allow the button and key listeners to share the code for that action. For the buttons, use the setAction(Action a) method to attach the actions. For the keyboard input, map those actions into the InputMap for the frames content pane like so

getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE,0),"My Action");
        getRootPane().getActionMap().put("My Action",new MyAction());

This will allow the key binding to respond within the focused window. More info on key binding in this manner can be found here: How To Use Key Bindings

I'm not sure I understand what to do with AbstractAction.
Is this something like what the input and action maps should look like?

getRootPane().getInputMap(btnMiddleC.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_C,0),"Play C");
getRootPane().getActionMap().put("Play C",new CButton.doIT());

I was looking them up before but I couldn't really understand them.
I wouldn't be the world's strongest programmer.
I'll include my entire program here for whatever its worth.
Its fully commented, so you can breeze through it that way if you so wish.
I left out the code for Class DButton as its the same as Class CButton.
Sorry about the lack of Object Orientation. Ha.
Still working on that.

// Import classes.
import javax.sound.midi.*;
import java.util.*;
import java.io.*;
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.event.*;
import javax.swing.*;
import java.net.*;

// Create GUI and its contents.
public class displayGUI extends JFrame
{
// Initialize all swing objects.
private JPanel pnlNorth = new JPanel(); // Create north quadrant. 
private JPanel pnlSouth = new JPanel(); // Create south quadrant.
	
// Create buttons.
private JButton btnMiddleC = new JButton("Middle C");
private JButton btnMiddleD = new JButton("Middle D");

// Constructor for the GUI.
public displayGUI()
{
	// Add buttons to panels.
	pnlSouth.add(btnMiddleC);
	pnlSouth.add(btnMiddleD);

	// Setup Main Frame.
	getContentPane().setLayout(new BorderLayout()); // Add layout to frame.
	getContentPane().add(pnlNorth, BorderLayout.NORTH); // Add panel to layout.
	getContentPane().add(pnlSouth, BorderLayout.SOUTH); // Add panel to layout.
		
	// Add action listeners.
	btnMiddleC.addActionListener(new CButton());
	btnMiddleD.addActionListener(new DButton());
		
	// Add key listeners.
	btnMiddleC.addKeyListener(new CButton());
	btnMiddleD.addKeyListener(new DButton());
}
	
// Display Frame.
 	
public void launchFrame()
{
	setTitle("Keyboard");
	setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // Allow frame to close.
        setSize(1000,650); // Set frame size.
        setVisible(true); // Allow frame to be visible.
}
	
// Create class to play a note.
public class MidiSynthesizer 
{
	// Array containing values for MIDI notes.
	int[] notes = new int[]{48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83};
		
	// Method to access, play and stop a note.
	void playIt(int playnote)
	{
	// Enclose a block of code that can generate errors, create catches.
	try 
	{
		// Create synthesizer to generate tone.
		Synthesizer synthesizer = MidiSystem.getSynthesizer();
		// Open the synthesizer so it can accquire any resources it needs.
		synthesizer.open();
		// Obtains the set of MIDI channels controlled by this synthesizer.
		MidiChannel channel = synthesizer.getChannels()[0];

		// Starts the specified note sounding.
		channel.noteOn(playnote, 50);
		// Enclose a block of code that can generate errors, create catches.
		try 
		{
		// Specifies the length of the note.
		Thread.sleep(200);
		} 
		// Thrown when a thread is waiting, sleeping or paused and another thread interrupts it.
		catch(InterruptedException e) 
		{
		// Print error message to console window.
		e.printStackTrace();
		} 
		// Always executed when the try block is exited, no matter how the try block is exited.
		finally 
		{
		// Turns the specified note off.
	        channel.noteOff(playnote);
	         }
		} 
                // Thrown when a MIDI tone unavailable.
		catch(MidiUnavailableException e) 
		{
			// Print error message to console window.
			e.printStackTrace();
		}
	}
}

// Class for CButton.
public class CButton implements ActionListener, KeyListener
{
	// Create instance of class.
	MidiSynthesizer midisynthesizer = new MidiSynthesizer();
		
	// Method to pass relevant note to the MidiSynthesizer class.
	public void doIT()
	{	
	// Set the index of the note associated with this button.
           
	int playnote = midisynthesizer.notes[12];
	// Send index to array of notes to play.
	midisynthesizer.playIt(playnote);
	}
		
	// Method to perform an action when the button is interacted with.
	public void actionPerformed(ActionEvent e)
	{
	// Call the doIT method..
	doIT();
	}
		
	// Invoked when a key has been typed.
	public void keyTyped(KeyEvent e)
	{}
		
	// Invoked when a key has been pressed.
	public void keyPressed(KeyEvent e)
	{
	// Returns the integer code for the key on the keyboard and if keyCode is equal to VK_C (ASCII C)... 
	if(e.getKeyCode() == KeyEvent.VK_C)
	{
	// ...call the doIT method.
	doIT();
	}
        }

	// Invoked when a key has been released.
	public void keyReleased(KeyEvent e)
        {}
	}
	
	// Class for DButton.
        // Exact same as class CButton.
	public class DButton implements ActionListener, KeyListener
	{......}
	
	// Main.
	public static void main(String args[])
	{  
		// Create object for GUI.
		displayGUI frame = new displayGUI();
		// Display GUI.
		frame.launchFrame();
   
	}
}
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.