1

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.

Riccardo Vailati
  • 203
  • 1
  • 11
  • 1
    Can you show your code? – Tripp Kinetics Aug 03 '15 at 17:41
  • 5
    *"I have two JFrames.."* That's where the GUI starts to go wrong. See [The Use of Multiple JFrames, Good/Bad Practice?](http://stackoverflow.com/q/9554636/418556) – Andrew Thompson Aug 03 '15 at 17:42
  • 1
    Please don't post all of your code. Instead post a shortened, runnable example that reproduces your problem. See [MCVE](http://stackoverflow.com/help/mcve) or [SSCCE](http://sscce.org/). – Lukas Rotter Aug 03 '15 at 17:44

2 Answers2

1

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
     }
  });
ControlAltDel
  • 33,923
  • 10
  • 53
  • 80
  • This sounds like a promising apporach but I can't figure out how to dispatch the event to the JTextField. Just calling text.dispatchEvent (e) throws a wall of red text. Any suggestions? http://pastebin.com/Uh7xjAw8 – Riccardo Vailati Aug 03 '15 at 19:23
  • Nevermind, figured it out, I just had to call the redispatchEvent method (duh). Now it works like a charm, thank you :) – Riccardo Vailati Aug 03 '15 at 19:33
0

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);
        }
    }
}
Jeff Demanche
  • 624
  • 7
  • 25
  • That wouldn't work, I would not be able to use backspace, arrow keys and so on – Riccardo Vailati Aug 03 '15 at 18:34
  • You could always add on to the listener and check for keycode 8, 37 and 39, etc., then handle them separately by `JTextField.setCaretPosition(int)`, `setText()` and so on . Of course, if ControlAltDel's answer works, it's about a million times less complicated. – Jeff Demanche Aug 03 '15 at 18:42