0

I have a menu bar with a search-bar that is implemented with a JTextField like this:

public class Ui_Frame {
    private static JFrame f;
    private static DrawPanel drawPanel;

    public static void main(String[] args) {
        SwingUtilities.invokeLater(Ui_Frame::createAndShowGUI);
    }

    private static void createAndShowGUI() {

        f = new JFrame("Frame");
        drawPanel = new DrawPanel(); //A class that extends JPanel where I draw

        JMenuBar menubar = new JMenuBar();
        JMenu j_menu_data = new JMenu("Data");
        JTextField j_menu_searchfield = new JTextField();
        j_menu_searchfield.setSize(new Dimension(100,20));
        menubar.add(j_menu_data);
        menubar.add(j_menu_searchfield);
        f.setJMenuBar(menubar);
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.add(drawPanel);
        f.pack();
        f.setVisible(true);
   }
}

I have KeyListeners for the DrawPanel class, these work just fine. The problem is that when I add the search bar JTextField to the menu bar as above, everything I write is being written to the text field and my key listeners do not trigger. I cannot "get out" of the text field, so If I click inside the area where I am drawing all the keys I press are still put into the text field.

I have tried getFocus() for the DrawPanel but to no avail.

How to solve this?

EDIT: DrawPanel class so you have all the classes you need to run it:

public class DrawPanel extends JPanel {
    public DrawPanel() {
        addKeyListener(new CustomKeyListener());
        this.setBackground(new Color(220,220,220));
        setBorder(BorderFactory.createLineBorder(Color.black));
        setFocusable(true);
        setVisible(true);
    }

    public Dimension getPreferredSize() {
        return new Dimension(500, 500);
    }

    protected void paintComponent(Graphics g) {
        Graphics2D g2D = (Graphics2D) g;
        super.paintComponent(g2D);
    }

    class CustomKeyListener implements KeyListener {
        @Override
        public void keyTyped(KeyEvent e) {
            if (e.getKeyChar() == KeyEvent.VK_SPACE) {
                System.out.println("Pressed SPACE");
            }

        }
        @Override
        public void keyPressed(KeyEvent e) { }
        @Override
        public void keyReleased(KeyEvent e) { }
    }
}
krise
  • 485
  • 1
  • 10
  • 22
  • 1
    1) `//A class that extends JPanel where I draw` Better to explain in code rather than a code comment. For better help sooner, [edit] to add a [MCVE] or [Short, Self Contained, Correct Example](http://www.sscce.org/). 2) For Swing, we typically use [key bindings](https://docs.oracle.com/javase/tutorial/uiswing/misc/keybinding.html) rather than the lower level `KeyListener`. – Andrew Thompson Sep 07 '20 at 11:27
  • 1
    Key events are dispatched to the component with focus. By default a JPanel is not focusable so the key events are dispatched to the text field. – camickr Sep 07 '20 at 14:25
  • @camickr I know, but how do I solve that ? There must be a way to have a searchbar and a drawing panel and respond differently to the keys being pressed depending on which component is active, right? – krise Sep 07 '20 at 14:32
  • That is what key bindings are for. You have posted a [mre] so we can't give a more specific answer. – camickr Sep 07 '20 at 14:44
  • okay ill have a look at the key bindings. I added the DrawPanel class – krise Sep 07 '20 at 15:01
  • That is not an [mre]. We can't compile and test. There is no frame, not "search text field". So how does this demonstrate the problem? – camickr Sep 07 '20 at 15:58
  • Why can you not compile and test? If you copy the code above and put it in 2 classes you can run the thing. If you do, you see a window pop up consisting of a text input-field and a Jpanel. As the text input-field is active and I cannot "get out of it" the KeyListener for the JPanel does not fire, which is the problem described above. – krise Sep 07 '20 at 16:21

1 Answers1

2

When you launch your Swing application, the JTextField initially has the keyboard focus. You know this because you see the cursor flashing inside the JTextField.

Clicking on the DrawPanel with the mouse does not transfer the keyboard focus to the DrawPanel. You know this because after clicking the mouse inside the DrawPanel, the cursor is still flashing inside the JTextField.

You can transfer the keyboard focus from the JTextField to the DrawPanel by hitting the TAB key on the keyboard since that is the default focus traversal key. You know that the JTextField no longer has keyboard focus because there is no flashing cursor in it.

If you really want the DrawPanel to gain keyboard focus by clicking the mouse in it, you can add a MouseListener to DrawPanel, as demonstrated in the below code which is essentially your code (for class DrawPanel) with a MouseListener added.

Note that I did not change class Ui_Frame.

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

import javax.swing.BorderFactory;
import javax.swing.JPanel;

public class DrawPanel extends JPanel implements MouseListener {
    public DrawPanel() {
        addKeyListener(new CustomKeyListener());
        addMouseListener(this);
        this.setBackground(new Color(220,220,220));
        setBorder(BorderFactory.createLineBorder(Color.black));
        setFocusable(true);
        setVisible(true);
    }

    public Dimension getPreferredSize() {
        return new Dimension(500, 500);
    }

    protected void paintComponent(Graphics g) {
        Graphics2D g2D = (Graphics2D) g;
        super.paintComponent(g2D);
    }

    class CustomKeyListener implements KeyListener {
        @Override
        public void keyTyped(KeyEvent e) {
            if (e.getKeyChar() == KeyEvent.VK_SPACE) {
                System.out.println("Pressed SPACE");
            }
        }

        @Override
        public void keyPressed(KeyEvent e) { }

        @Override
        public void keyReleased(KeyEvent e) { }
    }

    @Override
    public void mouseClicked(MouseEvent mouseEvent) {
        System.out.println(this.requestFocusInWindow());
    }

    @Override
    public void mousePressed(MouseEvent mouseEvent) {
    }

    @Override
    public void mouseReleased(MouseEvent mouseEvent) {
    }

    @Override
    public void mouseEntered(MouseEvent mouseEvent) {
    }

    @Override
    public void mouseExited(MouseEvent mouseEvent) {
    }
}

Note that method requestFocusInWindow() returns true if it succeeds.

Abra
  • 19,142
  • 7
  • 29
  • 41