Java easiest keylistener - java

I know there was milions of questions about that, but I can't understand most of them. I've seen that people make something like that:
public void keyPressed(KeyEvent e)
{
if (e.getKeyCode()== KeyEvent.VK_Q)
//do something
}
but keyPressed must override methos of some class to work or be runned in other thread. I really don't know how to do that. Can someone give me code of the easiest keylistener for java.
It should work even when program is not focused (it's just console program).
import java.awt.AWTException;
import java.awt.Robot;
import java.awt.event.*;
import javax.swing.JFrame;
public class SquatCounter {
class MyKeyListener extends KeyAdapter{
public void keyPressed(KeyEvent e)
{
if (e.getKeyCode()== KeyEvent.VK_Q)
System.out.println("Key Q pressed!");
}
}
JFrame jf = new JFrame("title");
public SquatCounter() {
jf.addKeyListener(new MyKeyListener());
}
public static void main(String[] args) {
Key1 key = new Key1 ();
SquatCounter test = new SquatCounter();
}
}

When you setup the JFrame, add a KeyListener like this:
JFrame jf = new JFrame("title");
jf.addKeyListener(new MyKeyListener());
jf.setVisible(false);
(The jf.setVisible(false); stops the program window from appearing (only command line)
Then create a new class called MyKeyListener that extends KeyAdapter.
class MyKeyListener extends KeyAdapter{
public void keyPressed(KeyEvent e)
{
if (e.getKeyCode()== KeyEvent.VK_Q)
System.out.println("Key Q pressed!");
}
}
Now let me explain things a bit.
First, when you create a JFrame, it has no default KeyListener attached. Therefore, we have to create a class MyKeyListener to do that.
Secondly, we extended KeyAdapter instead of implementing KeyListener because there are a lot more methods than what you need in there. You only need to override the keypressed() method when you extends KeyAdapter but you have to implement all (I think it's 3) the other methods that you don't need for your purposes.
Lastly, if you want to do other methods like keyreleased(), just add it in to the MyKeylistener class and it will work.
Hope this helps!
EDIT: Per OP's request, it should be like this:
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
String line = "";
while (line.equalsIgnoreCase("q") == false) {
line = in.read();
System.out.println("Q is pressed!");
}
in.close();

Just add a KeyListener.
import java.awt.AWTException;
import java.awt.Robot;
import java.awt.event.*;
import javax.swing.JFrame;
public class SquatCounter {
JFrame jf = new JFrame("title") {{
setVisible(true);
setDefaultCloseOperation(3); // EXIT_ON_CLOSE
}};
public SquatCounter() {
jf.addKeyListener(new KeyListener() {
#Override
public void keyPressed(KeyEvent event) {
if (e.getKeyCode()== KeyEvent.VK_Q)
//do something
}
#Override
public void keyReleased(KeyEvent event) {
// different stuff
}
#Override
public void keyTyped(KeyEvent event) {
// more stuff
}
});
}
public static void main(String[] args) {
SquatCounter test = new SquatCounter();
}
}
Doing something out of focus has an answer here: Stackoverflow: Listening for input without focus in Java

Related

Java: simulate keypresses when mouse clicked?

So, I'm fairly new to programming and I like to fiddle with it and one day my friend asked me to make a program where when you click, "ctrl" and "s" would be "pressed". I looked at lots of forums trying to make a functional code but, since I'm new to Java, I only got separate pieces of codes and threw it all together.
My code looks like this:
import java.awt.event.MouseEvent;
import java.awt.*;
import java.awt.event.*;
import java.awt.Robot;
import java.util.Scanner;
public class MyClass {
public static void main(String args[]) {
Scanner keyboard = new Scanner(System.in);
System.out.println("press any key to exit.");
keyboard.next();
System.exit(0);
}
public void mouseClicked(MouseEvent evt) {
try {
Robot robot = new Robot();
// Simulate a key press
robot.keyPress(KeyEvent.VK_CONTROL);
robot.keyPress(KeyEvent.VK_S);
robot.keyRelease(KeyEvent.VK_S);
robot.keyRelease(KeyEvent.VK_CONTROL);
} catch (AWTException e) {
}
}
}
Your program has no GUI and, therefore, nothing to invoke your mouse listener. The code within the listener appears correct, all you need to do is search for how to create a basic GUI and add the mouse listener to it so you get the results you want.
The following code may help you to handle Ctrl + S
public class SwingApp1 extends JFrame implements KeyListener {
public SwingApp1() {
setSize(500, 500);
setLocationRelativeTo(null);
setBackground(Color.blue);
addKeyListener(this);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
SwingApp1 main = new SwingApp1();
main.setVisible(true);
}
#Override
public void keyTyped(KeyEvent evt) {
}
#Override
public void keyPressed(KeyEvent e) {
System.out.println("Pressed=>" + e.getKeyCode());
if (e.getKeyCode() == 83) {
System.out.println("Pressed Ctrl + S");
} // Ctrl + S
}
#Override
public void keyReleased(KeyEvent e) {
}}

How to use keyListener properly in Java

I am running into problems trying to use KeyListener in java.
I am trying to write a program that runs until a key is pressed, and then outputs that key.
This is a stepping stone to more elaborate code, so the use of a method to print the key pressed is just being used as a kind of prototype.
Here is the code:
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
public class keylistener implements KeyListener{
public keylistener(){
addKeyListener(this);
}
public void keyPressed(KeyEvent e){
int key = e.getKeyCode();
keylistener output = new keylistener();
output.print(key);
}
public void keyReleased(KeyEvent e){}
public void keyTyped(KeyEvent e){}
public void print(int key){
System.out.println(key);
}
public static void main(String[] args){
}
}
The program runs and then ends directly after.
I have never used KeyListener before, and I cannot figure out how to make the program wait for the key to be pressed.
The KeyListener is intended to be used in GUI apps, not in console apps as KeyListener requires GUI components to run. Usually in a console app you would use a BufferedReader and InputStreamReader.
Here is a console app that demonstrates the idea of using a while loop with the BufferedReader and InputStreamReader to keep the app running waiting for input. Although there are other ways to do this. I made this very explicit so you can grasp the concept.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class StackStuff {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
boolean runs = true ;
System.out.println("Press any key to kill this app...");
while(runs){
input =br.readLine();
if (!(input==null)){
System.out.println(input);
runs=false;
}
}
System.out.println("I am dead!!");
System.exit(0);
}
I don't think I've ever added a KeyListener to a console app, (probably because KeyListener is part of the AWT package, which mainly has GUI components), but here is a sample GUI app to demonstrate.
Your first problem, though, is that you should have added new keylistener() into your main method, though that has to be added to a component itself in order to be ran.
public class GuiMain extends JFrame { // A GUI Frame
public GuiMain() {
// Add the listener
this.addKeyListener(new KeyAdapter() {
#Override
public void keyPressed(KeyEvent e) {
super.keyPressed(e);
// Print out the code
System.out.println(e.getKeyCode());
}
});
// Show something
add(new JLabel("Hello World!"));
pack();
}
public static void main(String[] args) {
// Run the GUI
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
GuiMain gui = new GuiMain();
gui.setVisible(true);
}
});
}
}

Make a JTextField recieve input even with windows not focused

I'm working on a small personal project.
I have two JFrame windows, Viewer and Console.
Viewer only contains a subclass of JPanel, and it should respond to mouse input (clicking, mostly).
Console contains a button, a JTextField (the input), and a JTextArea (the output).
I need to make sure than when I press keys on my keyboard, the corresponding text appears in the Console JTextField, not only when the focus is held by the JTextField, but also when it's held any other component in my app.
In other words, I want the JTextField to accept input even right after I clicked on the Viewer frame.
Is this feasible?
In case that matters, I'm running win 8 x64 and I don't really care about portability (I'm the only one that will ever look at or use this code).
EDIT: here is an example of my code:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class main {
public static Viewer v;
public static Console c;
public static void main(String[] args) {
v=new Viewer();
c=new Console();
}
static class Viewer extends JFrame {
public Viewer(){
setSize(600,600);
getContentPane().add(new myPanel());
addMouseListener(new mouse());
setVisible(true);
}
}
static class myPanel extends JPanel{
public void paintComponent(Graphics g){
g.setColor(new Color((int)(Math.random()*255),(int)(Math.random()*255),(int)(Math.random()*255)));
g.fillRect(0, 0, 600, 600);
}
}
static class Console extends JFrame {
public Console(){
setSize(600,200);
JTextField text=new JTextField();
getContentPane().add(text);
setVisible(true);
}
}
static class mouse implements MouseListener{
#Override
public void mouseClicked(MouseEvent arg0) {
v.repaint();
}
#Override
public void mouseEntered(MouseEvent arg0) {
}
#Override
public void mouseExited(MouseEvent arg0) {
}
#Override
public void mousePressed(MouseEvent arg0) {
}
#Override
public void mouseReleased(MouseEvent arg0) {
}
}
}
In this example, after I click on the big window to change its color, if I want to write stuff in the other window I have to click on it first.
Can I suggest the KeyboardFocusManager? I've found this to be the easiest way to achieve what I believe you are trying to achieve
KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(
new KeyEventDispatcher() {
public void dispatchKeyEvent(KeyEvent ke) {
//TODO: fill this in
}
});
One inelegant solution is to create a KeyListener, which feeds typed characters to your console, although how exactly this happens depends on how you create your components. For the sake of this example I'll pretend to do it through a static method in your Console class (preferably you'd have access to an instance of Console):
public class ApplicationKeyListener implements KeyListener {
public ApplicationKeyListener() {
}
// Other necessary methods...
public void keyPressed(KeyEvent e) {
char pressed = e.getKeyChar();
Console.feedChar(pressed);
}
}
And then in Console, make sure your JTextField object is global and static, then set up the feedChar() method.
public class Console extends JFrame {
private static JTextField consoleTextField;
public Console() {
consoleTextField = new JTextField();
// ...
}
public static feedChar(char c) {
consoleTextField.setText(consoleTextField.getText() + c.toString());
}
}
Then finally you'd have to add this listener to all JFrames and their children.
public class Viewer extends JFrame {
public Viewer() {
ApplicationKeyListener kl = new ApplicationKeyListener();
addKeyListener(kl);
for (Component child : this.getComponents()) {
child.addKeyListener(kl);
}
}
}

Adding a keylistener to a JMenuBar

I have the following code for a JMenuBar. How would I add my key listener CustomKeyListener to the entire JMenuBar?
package UI;
import javax.swing.*;
import java.awt.event.*;
import javax.swing.event.*;
import java.awt.Dimension;
import java.awt.Color;
import java.awt.*;
import java.awt.Point;
import java.awt.font.*;
import UI.*;
public class GuiDMenuBar extends JMenuBar
{
JMenu m_file,m_code;
JMenuItem mi_f_new,mi_f_open;
public GuiDMenuBar()
{
setBorderPainted(true);
makeFileMenu();
makeCodeButton();
}
void makeFileMenu()
{
m_file = new JMenu("File");
m_file.setMnemonic('F');
mi_f_new = new JMenuItem("New");
mi_f_new.setMnemonic('N');
mi_f_open = new JMenuItem("Open");
mi_f_open.setMnemonic('O');
mi_f_new.setAccelerator(KeyStroke.getKeyStroke("control N"));
mi_f_open.setAccelerator(KeyStroke.getKeyStroke("control O"));
m_file.add(mi_f_new);
m_file.add(mi_f_open);
add(m_file);
}
void makeCodeButton()
{
m_code = new JMenu("Code");
m_code.setMnemonic('C');
add(m_code);
}
public void addListeners(ActionListener al)
{
mi_f_new.addActionListener(al);
mi_f_open.addActionListener(al);
}
class CustomKeyListener implements KeyListener
{
#Override
public void keyTyped(KeyEvent e)
{
System.out.println("Type");
}
#Override
public void keyPressed(KeyEvent e)
{
System.out.println("Press");
}
#Override
public void keyReleased(KeyEvent e)
{
System.out.println("Release");
}
}
}
I have tried adding
m_code.setFocusable(true);
m_code.addKeyListener(new CustomKeyListener());
to the void makeCodeButton however that did not pick up when anything was typed for that one JMenu. This is why I want it added to the whole JMenuBar instead.
Edit to show full CustomKeyListener
class CustomKeyListener implements KeyListener
{
Robot Roby = null;
#Override
public void keyTyped(KeyEvent e)
{
char c = e.getKeyChar();
if(c==KeyEvent.VK_ENTER)
{
if(m_code.isSelected())
{
try
{
Roby = new Robot();
}
catch(AWTException awte)
{
awte.printStackTrace();
}
clcikComponent(m_file);
}
}
System.out.println("Type");
}
#Override
public void keyPressed(KeyEvent e)
{
System.out.println("Press");
}
#Override
public void keyReleased(KeyEvent e)
{
System.out.println("Release");
}
public void clcikComponent(Component comp)
{
Point p = comp.getLocationOnScreen();
System.out.println(p);
Roby.mouseMove(p.x,p.y);
Roby.mousePress(MouseEvent.BUTTON1_MASK);
Roby.mouseRelease(MouseEvent.BUTTON1_MASK);
}
}
I still think this is a bad idea. As a user I would find it very confusing to find out that using the Enter key on one menu invokes an Action, while it doesn't do anything on other menus. The suggestion I gave in my comment is a far better solution.
However, I was curious why it didn't work and I found out that focus is actually on the JRootPane when the menu is displayed (and events are only dispatched to the component with focus). So you could add the KeyListener to the root pane.
However, there is an easier approach. You can use the JMenu.addMenuKeyListener(...) method. The interface is the same as a KeyListener except all methods include "menu" in the name.

Detect CTRL+V in Swing App but keep original function

Wrting a chat application, I want the user to be able to send images out of his/her clipboard. For this, I would like to catch any CTRL+Vkeyboard input. Since pasting text should be possible as by default, the original ctrl+v-function (pasting text) must not be overridden.
I see can two approaches, of which none works for me:
1st: Taken from the official Java documentation: KEY LISTENER
editorPane.addKeyListener(new KeyListener() {
#Override
public void keyPressed(KeyEvent e) {
e.getKeyChar()
// when I press ctrl+v, ^ this is falsely a white square character, looks like (U+25A1). Plain v without ctrl does work.
e.getKeyCode()
// ^ this is falsely 0
// (e.getModifiersEx() correctly returns InputEvent.CTRL_DOWN_MASK)
}
2nd: KEY BINDING
InputMap iMap = editorPane.getInputMap(condition);
ActionMap aMap = editorPane.getActionMap();
iMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_V, InputEvent.CTRL_DOWN_MASK), "ctrlV");
aMap.put("ctrlV", new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
// works, but overrides natural ctrl+v function!
}
});
Any ideas?
Note: I am using a "foreign" keyboard layout (German). But I can't see why this should make any difference - I would pretty much like to have my application work internationally.
Cheers
edit. Alt+SomeKey however is correctly recognized by the KeyListener
edit2. after changing keyboard layout to US, problem persists.
Stick to Keybindings: KeyListener is a low-level API, while Keybindings will provide you consistent, predictable and robust behaviour.
The solution here is quite easy. You can simply combine the actions yourself by adding a CombinedAction class that will execute the "original" action bound to CTRL+V and the "custom" action you want to execute.
See a small example below combining both actions (here my custom action is a Sysout):
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import javax.swing.JComponent;
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.KeyStroke;
import javax.swing.ScrollPaneConstants;
public class TestEditorPane {
private JEditorPane editorPane;
public static class CombinedAction implements ActionListener {
private final ActionListener action1;
private final ActionListener action2;
public CombinedAction(ActionListener action1, ActionListener action2) {
super();
this.action1 = action1;
this.action2 = action2;
}
#Override
public void actionPerformed(ActionEvent e) {
if (action1 != null) {
action1.actionPerformed(e);
}
if (action2 != null) {
action2.actionPerformed(e);
}
}
}
public TestEditorPane() {
}
private void initUI() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// JTEXTBOX
editorPane = new JEditorPane();
KeyStroke ctrlV = KeyStroke.getKeyStroke(KeyEvent.VK_V, KeyEvent.CTRL_DOWN_MASK);
final ActionListener ctrlVAction = editorPane.getActionForKeyStroke(ctrlV);
editorPane.registerKeyboardAction(new CombinedAction(ctrlVAction, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("This is my action on CTRL+V");
}
}), ctrlV, JComponent.WHEN_FOCUSED);
// JSCROLLPANE
JScrollPane scroll1 = new JScrollPane(editorPane);
scroll1.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
scroll1.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
frame.add(scroll1);
frame.setSize(400, 400);
frame.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
TestEditorPane test = new TestEditorPane();
test.initUI();
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
}

Categories