Get KeyPressed when using JCanvas - java

I am creating a simple Java application using JCanvas, I need to get the key code of a key pressed by the user: The following is a simplified version of the Java Code
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.util.EventObject;
import java.awt.event.*;
// myJavaFiles project contains JCanvas & JEventQueue Classes
import myJavaFiles.*;
import javax.swing.*;
public static void main(String[] args) {
JCanvas canvas = new JCanvas();
JEventQueue events = new JEventQueue();
events.listenTo(canvas, "canvas");
JFrame frame = new JFrame();
frame.setSize(700, 700);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setFocusable(true);
frame.add(canvas);
while (true) {
if (events.hasEvent()){
EventObject event = events.waitEvent();
if(JEventQueue.isKeyPressed(event)){
int keycode = events.getKeyCode(event);
// USE KEYCODE!!!
}
}
canvas.sleep(10);
canvas.clear();
}
}
Everything works, (I omitted a lot of the non relevant code), except for getting the key pressed, I did notice that events.hasEvent doesn't even seem to be true when I press a key!
Please help! What am I doing wrong?

It's a bit difficult without the code for JCanvas and JEventQueue, but normally I would use a key listener for a panel that contains the canvas:
//frame.add(canvas);
final JPanel panel = new JPanel();
panel.add(canvas);
frame.getContentPane().add(panel);
panel.addKeyListener(new KeyAdapter() {
#Override
public void keyPressed(final KeyEvent keyEvent) {
System.out.println("keyEvent.getKeyCode(): " + keyEvent.getKeyCode());
}
});

Related

Why won't my Java Swing Keybinds work with Tab but they work fine with Space?

I'm making a game that uses Java Swing's keybinding. In that game, all the keybinds work fine, until I swap tabs and tab back in (tabs here referring to windows and not the tab key), in which case certain keys (most notably the tab key) no longer work (many other of the other keys work fine).
I made a new test class to try and debug this, but it just created a new problem where I wrote identical keybinds for tab and space, but only space works. I believe it has to do with the tab key already having a default keybind with JFrame since before, I had solved an issue with space not working due to JButton having a default space keybind. So here, I tried to unbind the tab key before adding my keybind, but it still didn't work. Here is the base code I have right now:
import java.awt.BorderLayout;
import java.awt.*;
import java.awt.Dimension;
import javax.sound.midi.Instrument;
import javax.sound.midi.MidiChannel;
import javax.sound.midi.MidiSystem;
import javax.sound.midi.MidiUnavailableException;
import javax.sound.midi.Synthesizer;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JRootPane;
import javax.swing.KeyStroke;
import java.awt.event.*;
public class test1 {
static JFrame frame;
public static void main(String[] args) {
frame = new JFrame();
int IFW = JComponent.WHEN_IN_FOCUSED_WINDOW;
frame.setSize(new Dimension(400, 400));
frame.setDefaultCloseOperation(frame.EXIT_ON_CLOSE);
// frame.pack();
JRootPane rootpane = frame.getRootPane();
frame.setLayout(null);
frame.setVisible(true);
rootpane.getInputMap(IFW).put(KeyStroke.getKeyStroke(KeyEvent.VK_TAB, 0), "space");
rootpane.getInputMap(IFW).put(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0), "space");
rootpane.getActionMap().put("space", new spaceAction());
}
public static class Frame extends JFrame implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
}
public Frame() {
super("Test");
}
}
public static class spaceAction extends AbstractAction {
#Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
System.out.println("a");
}
}
}
Here, pressing space prints "a", but pressing tab doesn't.
I tried looking up solutions to this, but most of the fixes involved using JComponent.WHEN_IN_FOCUSED_WINDOW, which I do use here.
Any help?

KeyListener/KeyBindings and order of adding components

In my program a JPanel component which is operated by listener using KeyBindings (changed that from KeyListeners already after reading about issues with focusing) is added to a JFrame. Task of this app is to simply move drawn figure around using arrow keys.
This works perfectly until i add another component before drawing board (JPanel with three buttons).
I tested both Keybindings and KeyListener and both methods have the same issue.
If I add components after drawing board keybindings starts to work again.
Here is my UI class where i add components.
EDIT: removed uncleaned code
I would like to understand Java a bit more so any answer is very appreciated.
Edit: I cleaned my code and created "minimal" example of the problem.
Thank you Andrew for heads up.
Program should print "movingup" in console after pressing arrow up.
The problem occurs here:
container.add(buttons); //after adding this Key Bindings stops working
container.add(board);
And the question is: Why order of adding components makes Key Bindings to stop working? If i add buttons after board Key Binding is working.
Class with the problem (used for creating frame and adding components)
import java.awt.Container;
import java.awt.Dimension;
import java.awt.GridLayout;
import javax.swing.JFrame;
import javax.swing.KeyStroke;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.WindowConstants;
public class UserInterface implements Runnable {
private static final String MOVE_UP = "moveUP";
private JFrame frame;
public UserInterface() {
}
#Override
public void run() {
frame = new JFrame("Board");
frame.setPreferredSize(new Dimension(500, 400));
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setLayout(new GridLayout());
createComponents(frame.getContentPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
private void createComponents(Container container) {
DrawingBoard board = new DrawingBoard();
container.add(new JButton()); //after adding this figure stops moving - arrow keys doesn't work
container.add(board);
MovingUpwards up = new MovingUpwards(board);
board.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
board.getInputMap().put(KeyStroke.getKeyStroke("UP"), MOVE_UP);
board.getActionMap().put(MOVE_UP, up);
}
public JFrame getFrame() {
return frame;
}
}
Rest of the used classes for testing purposes:
import javax.swing.SwingUtilities;
public class Main {
public static void main (String[] args) {
UserInterface ui = new UserInterface();
SwingUtilities.invokeLater(ui);
}
}
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JPanel;
public class DrawingBoard extends JPanel {
public DrawingBoard() {
super.setBackground(Color.WHITE);
}
#Override
protected void paintComponent (Graphics graphics) {
super.paintComponent(graphics);
}
}
import java.awt.Component;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
public class MovingUpwards extends AbstractAction {
private Component component;
public MovingUpwards(Component component) {
this.component = component;
}
#Override
public void actionPerformed(ActionEvent a) {
System.out.println("movingup");
}
}
The key bindings work fine for me. Check out the Motion Using Key Bindings example found in Motion Using the Keyboard.
I changed the code:
frame.add( content );
frame.add(left, BorderLayout.NORTH);
to:
frame.setLayout(new GridLayout());
frame.add(left);
frame.add( content );
to better simulate your logic.
If you need more help then read Andrew's comment above. Simplify your code to demonstrate the problem so we can "easily" test it by copying and compiling a single source file, the way you can test the code found in the link above.

JAVA JButton in a different class refuses to activate when pressed

I'm failing to understand why my yankee and whiskey JButtons aren't working. Right now I only want them to close the program when romeo is greater than 1 and sierra is greater than 1.
import java.awt.*;
import java.lang.*;
import javax.swing.*;
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.InputEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.*;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.JPanel;
import java.util.Scanner;
public class AlphaMenu extends JFrame /*implements actionPerformed*/
{
private GraphicsDevice gamma;
public JButton charlie, zulu, yankee, xray;
public JFrame beta;
public JPanel delta, echo, foxtrot, golf, hotel;
public JTextArea whiskey, victor;
public BorderLayout uniform;
public ImageIcon bg;
public JLabel tango;
public int sierra, romeo;
public Integer quebec, papa;
public ActionEvent oscar;
public ActionEvent november;
public AlphaMenu()
{
//Initialization of Objects
charlie = new JButton("EXIT");
zulu = new JButton("Enter Time");
yankee = new JButton("Enter Amount of Money");
xray = new JButton("Calculate");
sierra = 0;
romeo = 0;
quebec = new Integer(0);
papa = new Integer(0);
whiskey = new JTextArea(2, 15);
victor = new JTextArea(2, 15);
bg = new ImageIcon("background.gif");
beta = new JFrame();
delta = new JPanel();
echo = new JPanel();
foxtrot = new JPanel();
golf = new JPanel();
hotel = new JPanel();
uniform = new BorderLayout();
ImageIcon bg = new ImageIcon("background.gif");
tango = new JLabel("");
tango.setIcon(bg);
//Modification of panels
beta.add(delta, uniform.PAGE_END);
beta.add(golf, uniform.PAGE_START);
beta.add(echo, uniform.LINE_START);
beta.add(foxtrot, uniform.LINE_END);
beta.add(hotel, uniform.CENTER);
golf.add(tango);
//Modification of JButton charlie & adding of JButtons
charlie.setPreferredSize(new Dimension(100, 50));
delta.add(charlie);
charlie.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
System.exit(0);
}
});
echo.add(whiskey);
echo.add(yankee);
foxtrot.add(victor);
foxtrot.add(zulu);
//Modification of JFrame beta
beta.setUndecorated(true);
beta.setExtendedState(JFrame.MAXIMIZED_BOTH);
beta.setResizable(false);
beta.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
beta.setVisible(true);
}
public void buttonSetup() throws NumberFormatException
{
//Modification of JButton yankee & JTextArea whiskey & int sierra
romeo = quebec.parseInt(whiskey.getText());
yankee.setPreferredSize(new Dimension(300, 50));
yankee.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent oscar)
{
System.exit(0);
}
});
//Modification of JButton zulu & JTextArea victor & int romeo
sierra = papa.parseInt(victor.getText());
zulu.setPreferredSize(new Dimension(300, 50));
zulu.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent november)
{
System.exit(0);
}
});
}
public void actionPerformed(ActionEvent e)
{
}
public static void main(String[] args)
{
new AlphaMenu();
}
}
So, you have two JTextArea (JTextField would probably be better) and a button. you want some buttons to execute exit when the text of both textareas is an integer greater than 1.
seems that your buttonSetup() function isn't called anywhere.
Anyway, I'd create an ActionListener that reads the texts, converts to integer, tests your condition and executes exit(). This ActionListener should be added to all the buttons you want to perform the action
final ActionListener al = new ActionListener() {
public void actionPerformed(ActionEvent event) {
try {
final int intRomeo = Integer.parseInt(romeo.getText());
final int intSierra = Integer.parseInt(sierra .getText());
if (intRomeo > 1 && intSierra > 1) {
// whatever you want to do
System.exit(0);
}
} catch (/*NumberFormat*/ Exception e) {
// ...not integers
}
};
}
whiskey.addActionListener(al);
yankee.addActionListener(al);
I have to add: the variable names you are using are really bad. Consider choosing something more significative.
For starters, readability...it would probably help the "sloppiness" if you used more appropriate names for your variables, indented different sections of code, and used comments to help describe sections in layman's terms. Maybe "btnExit" and "btnCalculate" would help make things a little easier to navigate.
Moving forward, you also don't have two different classes here, you have one class with several methods. Which is fine but wanted to inform you of that. I think maybe you need to add the buttons to their panels after your action listeners and formatting for each button. I'm just getting into some swing stuff myself and I've noticed moving the .add() functions around in the code has helped when I run into issues like this. Try the following bellow. I indented and used new naming conventions for the comments, but the code uses your convention.
//add the pnlEcho to frmBeta
beta.add(echo, uniform.LINE_START);
//format btnYankee
yankee.setPreferredSize(new Dimension(300, 50));
//btnYankee action listener
yankee.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) { //default action event
System.exit(0); //you could use this
beta.dispose(); //or you could dispose the frame and
//do more work after it is gone
}
});
//add btnYankee to pnlEcho
echo.add(yankee);
I'm failing to understand why my yankee and whiskey JButtons aren't
working
The variable wiskey is not JButton type but JTextArea type.

get keystrokes in java without focusing?

i wanted to make a java program for getting keystrokes without focusing and without keyevent class object for my project ..
is there any way to do so..??
i tried this but it is not fulfilling my requirements!!
import java.awt.Container;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
import javax.swing.text.Keymap;
public class key1 {
private static void showUI() {
JFrame jFrame = new JFrame("");
jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container container = jFrame.getContentPane();
JTextField txt = new JTextField();
container.add(txt, BorderLayout.NORTH);
ActionListener actListener = new ActionListener() {
#Override
public void actionPerformed(ActionEvent event) {
System.out.println(event.getActionCommand() + " selected");
}
};
JPanel jPane = new JPanel();
JButton defaultButton = new JButton("Hit Enter");
defaultButton.addActionListener(actListener);
jPane.add(defaultButton);
JButton otherButton = new JButton("Onother Button");
otherButton.addActionListener(actListener);
jPane.add(otherButton);
container.add(jPane, BorderLayout.SOUTH);
Keymap map = txt.getKeymap();
KeyStroke stroke = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0, false);
map.removeKeyStrokeBinding(stroke);
jFrame.getRootPane().setDefaultButton(defaultButton);
jFrame.setSize(350, 250);
jFrame.setVisible(true);
}
public static void main(String args[]) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
showUI();
}
});
}
}
I don't believe this is possible at the Swing level..the entire KeyEvent API revolves around some Component having focus :(
In fact, I'm pretty sure the JVM only generates events based on what the OS gives to it..and you can only get those events if something is in focus.
However, I've found a library that might do what you want. I have never used it though..just looked up out of curiosity:
http://code.google.com/p/jnativehook/

JButton stops working after several clicks with nothing else changed

I am trying to create a piano program where you click the key and using an actionlistener is plays the note from the jfugue library. For some reason after about 18 clicks without changing anything the buttons stop working. I cut down the code to analyze why this might happen, thus only two notes.
Thanks in advance for any advice!
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JComponent;
import java.awt.Color;
import javax.swing.JLayeredPane;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import javax.swing.JButton;
import javax.swing.*;
import org.jfugue.*;
public class ChordPlayer2 extends JComponent{
public ChordPlayer2(){
final Player player = new Player();
JFrame frame = new JFrame();
JButton cButton, csharpButton;
JPanel buttonPanel = new JPanel();
buttonPanel.setLayout(null);
buttonPanel.setLocation(0, 0);
buttonPanel.setSize(1700, 1000);
csharpButton = new JButton("");
csharpButton.setLocation(100, 150);
csharpButton.setSize(100,520);
buttonPanel.add(csharpButton);
cButton = new JButton("");
cButton.setLocation(0, 150);
cButton.setSize(160, 800);
buttonPanel.add(cButton);
class cClicker implements ActionListener {
public void actionPerformed(ActionEvent event) {
player.play("C");
}
}
class csClicker implements ActionListener {
public void actionPerformed(ActionEvent event) {
player.play("C#");
}
}
ActionListener c = new cClicker();
cButton.addActionListener(c);
ActionListener cs = new csClicker();
csharpButton.addActionListener(cs);
buttonPanel.setOpaque(true);
//return buttonPanel;
frame.add(buttonPanel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(1700, 1000);
frame.setVisible(true);
}
public static void main(String[] args) {
//Schedule a job for the event-dispatching thread:
//creating and showing this application's GUI.
//JFrame.setDefaultLookAndFeelDecorated(true);
ChordPlayer2 demo = new ChordPlayer2();
}
}
This is a known bug in JFugue:
https://code.google.com/p/jfugue/issues/detail?id=49
The most recent version is claimed to fix this:
https://code.google.com/p/jfugue/downloads/detail?name=jfugue-4.1.0-20120125.jar&can=2&q=

Categories

Resources