Prevent jLabel from losing focus when clicking on a nested jcombobox - java

I am making an app that will have some 'rectangles' (myLabel) with a text (rectangleName). Whenever I click on that rectangle, a combobox (nameComboBox) is shown to change the name of it.
So this is the declaration of that class.
public class myLabel extends JLabel implements MouseListener,FocusListener{
//this.panel;
JComboBox nameComboBox;
String rectangleName;
I added some focus stuff to that class as you can see it implements FocusListener.
I want to show the combobox only when the recangle is focused and hide it otherwise. The problem that I have is that when I select a rectangle and it shows the combobox because it's focused, when I click on the combobox, the rectangle loses its focus so it hides the combobox. Any way to prevent this?
Edit:
Replying to #mKorbel, This is my SSCCE
import java.awt.Color;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingConstants;
public class MyJLabel extends JLabel implements MouseListener,FocusListener{
JComboBox nameComboBox;
JPanel mainPanel;
String name;
public MyJLabel() {
this.setLocation(10,10);
this.setBounds(20, 20,200,200);
this.setBackground(Color.LIGHT_GRAY);
this.setFocusable(true);
setOpaque(true);
setHorizontalAlignment(SwingConstants.CENTER);
setFont(getFont());
setText(this.name);
this.nameComboBox= new JComboBox(new String[] { "option1","option2","option3" });
this.nameComboBox.setBounds(40,40,100,50);
this.nameComboBox.setVisible(false);
this.addMouseListener(this);
this.addFocusListener(this);
}
#Override
public void focusGained(FocusEvent e) {
System.out.println("focus gained");
this.nameComboBox.setVisible(true);
}
#Override
public void focusLost(FocusEvent e) {
System.out.println("focus lost");
this.nameComboBox.setVisible(false);
}
#Override
public void mouseClicked(MouseEvent e) {
this.requestFocus();
}
#Override
public void mousePressed(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseReleased(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseEntered(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseExited(MouseEvent e) {
// TODO Auto-generated method stub
}
public static void main(String[] args) {
MyJLabel myjl=new MyJLabel();
JFrame fr = new JFrame();
fr.setLayout(null);
fr.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JComboBox otherCombo = new JComboBox(new String[] { "otherOption1","otherOption2","otherOption3" });
otherCombo.setBounds(40,400,100,50);
fr.add(myjl.nameComboBox);
fr.add(myjl);
fr.add(otherCombo);
fr.setSize(300,500);
fr.setVisible(true);
}
}
You must start clicking on the combo at the bottom and you'll see in the console that the focus is lost. click on the gray rectangle and the focus will be gained. Click on the combo inside the rectangle and the rectangle will lose and gain the focus instantly, so it's impossible to choose an item. I would like to not change the focus of the rectangle while I am interacting with its combobox.

Related

Neither Key Listener nor Document Listener fires for ComboBox

Found a simple JComboBox sample on java2 and expanded it to include both a DocumentListener and KeyListener
hoping to capture keystrokes done within the JComboBox.
Eventually those keystrokes will be captured to display the data which matches the keys entered.
For example, as the user types APP, all records beginning with A is return then AP is return and then all data beginning with APP. Basically doing a Filter on "APP*".
But for now, I am unable to get either a KeyListener or DocumentListener working.
Actually, it works sporadically and can't narrow down why. It seems to only work for the Enter key but would like for it to capture for all keystrokes.
Here is the code.
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.ComboBoxEditor;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.plaf.metal.MetalFileChooserUI;
public class JComboBoxFilter extends JPanel implements ItemListener {
public JComboBoxFilter () {
JComboBox jc = new JComboBox();
jc.addItem("A");
jc.addItem("AA");
jc.addItem("AAA");
jc.addItem("C");
jc.addItem("CC");
jc.addItem("CCC");
jc.addItem("B");
jc.addItem("BB");
jc.addItem("BBB");
jc.addItemListener(this);
add(jc);
ComboBoxEditor editor = jc.getEditor();
JTextField textField = (JTextField)editor.getEditorComponent();
textField.addKeyListener(new KeyListener()
{
#Override
public void keyPressed(KeyEvent arg0) {
runThisKeyListener();
}
#Override
public void keyReleased(KeyEvent arg0) {
runThisKeyListener();
}
#Override
public void keyTyped(KeyEvent arg0) {
runThisKeyListener();
}
private void runThisKeyListener()
{
System.out.println("Inside runThisKeyListener() : " + textField.getText());
}
});
DocumentListener textFieldDL = new DocumentListener()
{
#Override
public void insertUpdate(DocumentEvent e)
{
runThis();
}
#Override
public void removeUpdate(DocumentEvent e)
{
runThis();
}
#Override
public void changedUpdate(DocumentEvent e)
{
runThis();
}
private void runThis()
{
System.out.println("Inside runThis() : " + textField.getText());
}
};
textField.getDocument().addDocumentListener(textFieldDL);
}
public void itemStateChanged(ItemEvent ie) {
String s = (String)ie.getItem();
System.out.println(s);
}
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.getContentPane().add(new JComboBoxFilter ());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(200, 200);
frame.setVisible(true);
}
}
Is there anything wrong with the code or is there a Java rule or restriction not allowing this type of functionality?

See if a window loses focus

I have an undecorated JFrame with my own 'header' at the top. It works fine except for telling if the window is out of focus.
I've tried things like
if(!frame.hasFocus()
//Do stuff here
But this obviously won't work when I have other components in the window, such as a JTextField. I haven't found a way to do this so any help is appreciated.
Here is a sample code by which you can implement it:
import java.awt.event.FocusListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowFocusListener;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class SwingTest {
public static void main(String args[])
{
swing();
}
public static void swing()
{
JFrame g= new JFrame("First");
g.setVisible(true);
g.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
g.setSize(300, 300);
g.setLayout(null);
JLabel l=new JLabel("Times Windows Lost Focus : 0");
l.setBounds(20,10, 200, 60);
g.add(l);
g.addWindowFocusListener( new WindowFocusListener() {
int c=0;
#Override
public void windowLostFocus(WindowEvent e) {
c++;
}
#Override
public void windowGainedFocus(WindowEvent e) {
l.setText("Times Windows Lost Focus :"+c);
//System.out.println(c);
// TODO Auto-generated method stub
}
});;
}
}

KeyListener won't do anything

I'm trying to add a keylistener to JFrame but whenever I click a button, nothing happens. I am trying to get the keylistener to just print something basic but whenever i try to use an if statement nothing happens in the console.
package gui;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import javax.swing.*;
import javax.swing.JButton;
public class KeyListener implements java.awt.event.KeyListener {
ArrayList <JButton> _buttons;
JFrame _frame1;
public KeyListener(ArrayList <JButton> buttons, JFrame frame1){
_buttons = buttons;
_frame1 = frame1;
_frame1.addKeyListener(this);
_frame1.requestFocusInWindow();
_frame1.setFocusable(true);
this.keyTyped();
}
#Override
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
if (e.getKeyCode() == KeyEvent.VK_LEFT){
System.out.println("yes");
}
}
#Override
public void keyPressed(KeyEvent e) {
// TODO Auto-generated method stub
}
#Override
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub
}
}
That is my keylistener class
This is my game class
package model;
import java.awt.event.KeyListener;
import javax.swing.*;
public class Game implements Runnable{
KeyListener _keylistener;
#Override
public void run() {
JFrame frame1 = new JFrame("KeyBricks");
frame1.setVisible(true);
JPanel panel1 = new JPanel();
frame1.addKeyListener(_keylistener);
model.Board board = new model.Board(panel1);
frame1.add(panel1);
frame1.pack();
frame1.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
}
}
You could register a KeyEventDispatcher:
KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(new KeyEventDispatcher() {
#Override
public boolean dispatchKeyEvent(KeyEvent e) {
System.out.println("dispatchKeyEvent: "+e);
return false;
}
});
Note that the registered KeyEventDispatchers will receive KeyEvents before they are dispatched to their targets, allowing to retarget the event, consume it, dispatch the event itself, or make other changes.

Can't figure out error with ActionListener

The following is my program. the goal is to convert from a roman numeral to an Arabic number after a user types in the numeral and presses the enter key.
This is a homework assignment and we are forced to user JTextAreas in lieu of JTextFields.
My error exists on the line: enterRomanNumber.addActionListener(handler);
The error reads:
"The method addActionListener(ArabicToRomanGUI.HandlerForTextArea) is
undefined for the type JTextArea"
I can't seem to figure out why I am getting this error or how to correct it, can someone please advise.
import java.awt.FlowLayout;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.ActionEvent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextField;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextArea;
public class ArabicToRomanGUI extends JFrame
{
private static final long serialVersionUID = 1L;
private JTextArea enterRomanNumber = new JTextArea();
JLabel label = new JLabel();
JPanel panel = new JPanel();
JFrame frame = new JFrame();
//TestArea contructor adds jtextArea to jframe
public ArabicToRomanGUI()
{
super("Convert a Roman Numeral");
setLayout(new FlowLayout());
//Text field to enter a roman numeral
enterRomanNumber = new JTextArea(1,25);
enterRomanNumber.setText("Delete this text and Enter a Roman Numerial Here!");
//enterRomanNumber.setAlignmentX(0);
//enterRomanNumber.setAlignmentY(0);
add(enterRomanNumber);
HandlerForTextArea handler = new HandlerForTextArea();
enterRomanNumber.addActionListener(handler);
}
private class HandlerForTextArea implements ActionListener
{
//used to process textArea events
#Override
public void actionPerformed(ActionEvent e)
{
String userInput = "";
userInput = enterRomanNumber.getText();
userInput = userInput.toUpperCase();
ConversionLogic.ConvertFromRomanToArabic(userInput); //converts user string of Roman numerals to an int in arabic
String arabicNumberAsString = ConversionLogic.getConvertedRomanNumeral();
enterRomanNumber.setText(arabicNumberAsString);
//user pressed enter in JTextField enterNumberField
if(e.getSource() == enterRomanNumber)
{
//enterRomanNumber.setText(arabicNumberAsString);
if (ConversionLogic.getCheckFail() == true)
{
JOptionPane.showMessageDialog(frame, "The Roman Numeral entered is Invalid", "Error", JOptionPane.ERROR_MESSAGE);
}
else
{
JOptionPane.showMessageDialog(frame, "The arabic equivalent is " + arabicNumberAsString + "." , "Conversion Successful", JOptionPane.PLAIN_MESSAGE);
}
}
}
}
}//end inner class TextAreaHandler
For a better answer, see #MadProgrammer 's answer.
My solution:
There is no ActionListener for JTextArea.
So just use KeyListener instead
HandlerForTextArea handler = new HandlerForTextArea();
enterRomanNumber.addKeyListener(handler);
Implements KeyListener
private class HandlerForTextArea implements KeyListener
{
#Override
public void keyPressed(KeyEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void keyReleased(KeyEvent arg0) {
// TODO Auto-generated method stub
if (arg0.getKeyCode() == VK_ENTER){
// TODO Your bussiness
}
}
#Override
public void keyTyped(KeyEvent arg0) {
// TODO Auto-generated method stub
}
}
KeyListeners are NEVER appropriate solutions to use with text components, if you want to be notified when a text component changes, you use a DocumentListener, if you want to change/filter what can be entered into a text component, you use a DocumentFilter, if you need to change a special key, like Enter, you should use a key binding
See How to Use Key Bindings for more details.
One of the problems you could have with KeyListener is not knowing when the key stroke is processed by the text component, in your case, it may not be a major issue, but it could change the way the program works on different platforms.
Instead, you can override the JTextArea's key binding for the Enter key (named insert-break). This provides you with the ability to actually change the behavior of the key stroke, or, in your case, manage how you process the event. For example, this replaces the Action for the text area's Enter key, but retains the previous/default behavior...
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.ActionMap;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class KeyBindingsTest {
public static void main(String[] args) {
new KeyBindingsTest();
}
public KeyBindingsTest() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private JTextArea ta;
public TestPane() {
ta = new JTextArea(10, 20);
ActionMap am = ta.getActionMap();
Action proxy = am.get("insert-break");
am.put("insert-break", new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
// You can process the event through the original action BEFORE
// you do your own processing
//proxy.actionPerformed(e);
System.out.println("You pressed the enter key, you can have candy");
// Or you can process the event through the original action AFTER
// you do your own processing, you have now gained control
proxy.actionPerformed(e);
}
});
setLayout(new BorderLayout());
add(ta);
}
}
}
Now, you could even go to the extent for creating your own JTextArea which supported ActionPerformed...
public class ActionableTextArea extends JTextArea {
private String actionCommand;
public ActionableTextArea() {
installKeyBindings();
}
public ActionableTextArea(String text) {
super(text);
installKeyBindings();
}
public ActionableTextArea(int rows, int columns) {
super(rows, columns);
installKeyBindings();
}
public ActionableTextArea(String text, int rows, int columns) {
super(text, rows, columns);
installKeyBindings();
}
public ActionableTextArea(Document doc) {
super(doc);
installKeyBindings();
}
public ActionableTextArea(Document doc, String text, int rows, int columns) {
super(doc, text, rows, columns);
installKeyBindings();
}
protected void installKeyBindings() {
ActionMap am = getActionMap();
Action proxy = am.get("insert-break");
am.put("insert-break", new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
// You can process the event through the original action BEFORE
// you do your own processing
//proxy.actionPerformed(e);
fireActionPerformed();
// Or you can process the event through the original action AFTER
// you do your own processing, you have now gained control
proxy.actionPerformed(e);
}
});
}
public void addActionListener(ActionListener listener) {
listenerList.add(ActionListener.class, listener);
}
public void removeActionListener(ActionListener listener) {
listenerList.remove(ActionListener.class, listener);
}
public void setActionCommand(String actionCommand) {
this.actionCommand = actionCommand;
}
public String getActionCommand() {
return actionCommand;
}
protected void fireActionPerformed() {
ActionListener[] listeners = listenerList.getListeners(ActionListener.class);
if (listeners.length > 0) {
ActionEvent evt = new ActionEvent(this, ActionEvent.ACTION_PERFORMED, getActionCommand());
for (ActionListener listener : listeners) {
listener.actionPerformed(evt);
}
}
}
}

Simple KeyListener not working

I'm working on a really simple project in Java to try to understand how to use KeyListener.
I've created a Main class and a KeyListener, MouseListener class. I want to get something to happen when I press a keyboard key. So far the only thing that is working is "Hello" when I click.
Here is my code:
import javax.swing.JFrame;
import javax.swing.JPanel;
public class KeyPractice{
public static void main(String[] args) {
JFrame frame = new JFrame();
JPanel panel = new JPanel();
panel.addKeyListener(new KeyEar());
panel.addMouseListener(new KeyEar());
frame.add(panel);
frame.setVisible(true);
frame.setSize(400, 400);
}
}
And the Keylistener class....
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
public class KeyEar implements KeyListener, MouseListener {
public KeyEar(){
}
#Override
public void mouseClicked(MouseEvent arg0) {
System.out.println("Hello");
}
#Override
public void mouseEntered(MouseEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void mouseExited(MouseEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void mousePressed(MouseEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void mouseReleased(MouseEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void keyPressed(KeyEvent arg0) {
System.out.println("Hello");
}
#Override
public void keyReleased(KeyEvent arg0) {
System.out.println("Hello");
}
#Override
public void keyTyped(KeyEvent arg0) {
System.out.println("Hello");
}
}
JPanel isn't focusable JComponent, have to add Object/JComponents that is focusable or interact with KeyEvents
KeyListener isn't proper listener for Swing JComponents, for Swing is replaced with KeyBindings
A JPanel cannot gain focus for KeyListener to work.
The preferred approach is to use Key Bindings for Swing. You can map an Action to a KeyStroke even when a component doesn't have focus.
Key Binding Example
I had similar problem but its so simple to solve but you have to found how to solve it witch is not so easy task :D
so how to solve this ? I just set all my buttons as focusable false.
instanceOfYourButton.setFocusable(false);
thats it

Categories