Make ActionHandler Ignore Arrow Keys - java

How do I make Action Handler ignore arrow keys? Currently, when I try to use arrow keys to navigate my combo box, the combo box moves down/up once, changes the selection, and then triggers the Action Handler moving the focus to the button.
I would like to be able to navigate the combo box with the arrow keys, and hit Enter when I'm ready to move on to the next component.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class test {
JFrame window = new JFrame("testGUI");
JPanel windowPanel = new JPanel();
public static JLabel labelSize;
public static JComboBox<String> comboSize;
public static JLabel labelButton;
public static JButton buttonButton;
public test () {
super();
labelSize = new JLabel("Monster Size:");
String[] sizeChoices = { "None", "Tiny", "Small", "Medium", "Large", "Huge", "Colossal"};
comboSize = new JComboBox<String>(sizeChoices);
comboSize.setToolTipText("The creature's size.");
comboSize.addKeyListener(new KeyListener() {
#Override
public void keyTyped(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_ENTER){
comboSize.showPopup();
}
}
#Override
public void keyReleased(KeyEvent e) {
comboSize.showPopup();
}
#Override
public void keyPressed(KeyEvent e) {
}
});
labelButton = new JLabel("Button:");
buttonButton = new JButton();
buttonButton.addKeyListener(new KeyListener() {
#Override
public void keyTyped(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_ENTER)
buttonButton.doClick();
}
#Override
public void keyReleased(KeyEvent e) {
}
#Override
public void keyPressed(KeyEvent e) {
buttonButton.doClick();
}
});
windowPanel.setLayout(new FlowLayout());
windowPanel.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT);
windowPanel.add(labelSize);
windowPanel.add(comboSize);
windowPanel.add(labelButton);
windowPanel.add(buttonButton);
windowPanel.setVisible(true);
window.setSize(500, 500);
window.setLayout(new FlowLayout());
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setVisible(true);
window.add(windowPanel);
comboSize.addActionListener(handler);
buttonButton.addActionListener(handler);
}
ActionHandler handler = new ActionHandler();
public class ActionHandler implements ActionListener {
public void actionPerformed(ActionEvent eventFocus){
if (eventFocus.getSource() == comboSize){
buttonButton.requestFocusInWindow();
}
if (eventFocus.getSource() == buttonButton){
comboSize.requestFocusInWindow();
}
}
}
#SuppressWarnings("unused")
public static void main(String[] args) {
test GUITest = new test();
}
}

the combo box moves down/up once, changes the selection, and then triggers the Action Handler moving the focus to the button. I would like to be able to navigate the combo box with the arrow keys, and hit Enter when I'm ready to move on to the next component.
You can set a property on the combo box to only generate the ActionEvent when Enter is pressed by using the following:
comboBox.putClientProperty("JComboBox.isTableCellEditor", Boolean.TRUE);
Complete example:
/*
This works on non editable combo boxes
*/
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.plaf.basic.*;
import javax.swing.text.*;
public class ComboBoxAction extends JFrame implements ActionListener
{
public ComboBoxAction()
{
JComboBox<String> comboBox = new JComboBox<String>();
comboBox.addActionListener( this );
comboBox.addItem( "Item 1" );
comboBox.addItem( "Item 2" );
comboBox.addItem( "Item 3" );
comboBox.addItem( "Item 4" );
// This prevents action events from being fired when the
// up/down arrow keys are used on the dropdown menu
comboBox.putClientProperty("JComboBox.isTableCellEditor", Boolean.TRUE);
getContentPane().add( comboBox );
getContentPane().add( new JTextField(), BorderLayout.SOUTH );
}
public void actionPerformed(ActionEvent e)
{
System.out.println( e.getModifiers() );
JComboBox comboBox = (JComboBox)e.getSource();
System.out.println( comboBox.getSelectedItem() );
// make sure popup is closed when 'isTableCellEditor' is used
// comboBox.hidePopup();
}
public static void main(String[] args)
{
ComboBoxAction frame = new ComboBoxAction();
frame.setDefaultCloseOperation( EXIT_ON_CLOSE );
frame.pack();
frame.setVisible( true );
}
}
See Combo Box No Action for more information.

Related

unselect JCheckBox once re-clicked

I tried a number of other solutions posted on StackExchange but I can't get the JCheckBox to unselect when I click it again [after it's been selected].
I've tried the following and it just stays clicked even when re-clicked:
checkbox2.setSelected(false);
// check state
//if (checkbox2.isSelected()) {
// do something...
checkbox2.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent event) {
// return str;
//checkbox = (JCheckBox) event.getSource();
if (checkbox2.isSelected()) {
checkbox2.setSelected(false);
experimentalSelection = "ML";
System.out.println(experimentalSelection);
}
}
});
I assumed that if i added checkbox2.setSelected(false); then it would uncheck if it was already selected and then clicked.
The behavior that you describe -- making the JCheckBox unselected when a user clicks on an already selected JCheckBox is the check box's default/innate behavior. You don't have to do anything special for this to occur, and you certainly don't have to (or want to) change its selection state within a listener. For example:
import java.awt.Dimension;
import java.awt.event.ItemEvent;
import javax.swing.*;
public class GuiFun extends JPanel {
private JCheckBox checkbox = new JCheckBox("Foo");
public GuiFun() {
setPreferredSize(new Dimension(300, 150));
add(checkbox);
checkbox.setSelected(false);
checkbox.addItemListener(l -> {
if (l.getStateChange() == ItemEvent.SELECTED) {
System.out.println("CheckBox SELECTED");
} else {
System.out.println("CheckBox UNSELECTED");
}
});
}
private static void createAndShowGui() {
GuiFun mainPanel = new GuiFun();
JFrame frame = new JFrame("Gui Fun");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}

JTextField get no focus when in a heavy-weight popup

I want do display a text filed in a popup. When popup is completly over the application frame (MediumWeightPopup) - all works fine, but when a part of popup is outside of frame (HeavyWeightPopup) it cannot be focused. In this case caret is invisible and no text input is possible.
Here is my code:
import java.awt.BorderLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.Popup;
import javax.swing.PopupFactory;
import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;
public class PopupTest {
public static void main(String[] args) {
JFrame frm = new JFrame("Popup test");
JPanel p = new JPanel();
p.addMouseListener(new MouseAdapter() {
Popup pop;
#Override
public void mouseReleased(MouseEvent e) {
if (SwingUtilities.isRightMouseButton(e)) {
if (pop != null) {
pop.hide();
}
JPanel popupPanel = new JPanel(new BorderLayout());
JTextField field = new JTextField(20);
popupPanel.add(field);
pop = PopupFactory.getSharedInstance().getPopup(p, popupPanel, e.getXOnScreen(), e.getYOnScreen());
pop.show();
System.out.println("Popup type: " + pop.getClass().getName());
System.out.println("Can get focus? " + field.requestFocusInWindow());
}
}
});
frm.add(p);
frm.setSize(500, 300);
frm.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frm.setLocationRelativeTo(null);
frm.setVisible(true);
}
}
On right click near to right border of window I get a non-focusable text field. The same problem I get with any other component in popup that allows key control (for example JTable).
How can I focus a component in a HeavyWeightPopup?
I also struggled with this years ago. I can't figure out how to give initial focus to a component on the popup. Here are some of my questions/observations:
What is the Popup class used for?
I always thought that a Popup should have some basic functionality, such as the pupup should close when:
a) the escape key is pressed
b) the popup loses focus
The popup class provides none of the above functionality and in fact seems to require some obscure code to even get the keyboard focus to work properly.
Using a JWindow seems to provide the same functionality as a Popup.
JPopupMenu seems to support both of the above requirements.
Run the following program:
a) click on each of the buttons
b) click on an empty part of the frame
It appears to me that whenever you need a "popup" you should use a JPopupMenu.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.text.*;
public class PopupTest extends JFrame
{
String[] numbers = { "one", "two", "three", "four", "five" };
public PopupTest()
{
getContentPane().setLayout( new FlowLayout() );
getContentPane().setBackground(Color.YELLOW);
JButton popup = new JButton("Popup as Popup");
popup.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
popupPopup(e);
}
});
getContentPane().add(popup);
JButton window = new JButton("Window as Popup");
window.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
windowPopup(e);
}
});
getContentPane().add(window);
JButton menu = new JButton("PopupMenu as Popup");
menu.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
menuPopup(e);
}
});
getContentPane().add(menu);
}
private void popupPopup(ActionEvent e)
{
JList list = new JList(numbers);
list.setSelectedIndex(0);
PopupFactory factory = PopupFactory.getSharedInstance();
Popup popup = factory.getPopup(this, list, getLocation().x, getLocation().y+100);
//popup.show();
Window window = SwingUtilities.windowForComponent(list);
if (window != null)
{
window.setFocusableWindowState(true);
}
popup.show();
KeyboardFocusManager.getCurrentKeyboardFocusManager().focusNextComponent(list);
}
private void windowPopup(ActionEvent e)
{
JList list = new JList(numbers);
list.setSelectedIndex(0);
JWindow window = new JWindow(this);
window.getContentPane().add(list);
window.pack();
window.setVisible(true);
window.setLocation(getLocation().x + 200, getLocation().y+100);
window.addWindowListener( new WindowAdapter()
{
public void windowDeactivated(WindowEvent e)
{
System.out.println("deactivated");
}
});
}
private void menuPopup(ActionEvent e)
{
JList list = new JList(numbers);
list.setSelectedIndex(0);
JPopupMenu menu = new JPopupMenu();
menu.add( new JTextField(10) );
menu.add( list );
menu.show((Component)e.getSource(), 0, 100);
}
private static void createAndShowGUI()
{
JFrame frame = new PopupTest();
frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
frame.setSize(500, 200);
frame.setLocationRelativeTo( null );
frame.setVisible( true );
}
public static void main(String[] args)
{
EventQueue.invokeLater( () -> createAndShowGUI() );
/*
EventQueue.invokeLater(new Runnable()
{
public void run()
{
createAndShowGUI();
}
});
*/
}
}
Edit:
Based on Sergiy's answer, this code was close to working. The difference in the popupPopup() method is that the show() method needs to be invoked AFTER the window is made focusable. Code updated to reflect this change.
Source code analyse brought me another solution
pop = PopupFactory.getSharedInstance().getPopup(p, popupPanel, e.getXOnScreen(), e.getYOnScreen());
// some new stuff
Window win = SwingUtilities.windowForComponent(popupPanel);
if (win instanceof JWindow && win.getType() == Window.Type.POPUP) {
win.setFocusableWindowState(true);
}
// continue old stuff
pop.show();
So the complete example looks like
import java.awt.BorderLayout;
import java.awt.Window;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.JWindow;
import javax.swing.Popup;
import javax.swing.PopupFactory;
import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;
public class PopupTest {
public static void main(String[] args) {
JFrame frm = new JFrame("Popup test");
JPanel p = new JPanel();
p.addMouseListener(new MouseAdapter() {
Popup pop;
#Override
public void mouseReleased(MouseEvent e) {
if (SwingUtilities.isRightMouseButton(e)) {
if (pop != null) {
pop.hide();
}
JPanel popupPanel = new JPanel(new BorderLayout());
JTextField field = new JTextField(20);
popupPanel.add(field);
pop = PopupFactory.getSharedInstance().getPopup(p, popupPanel, e.getXOnScreen(), e.getYOnScreen());
Window win = SwingUtilities.windowForComponent(popupPanel);
if (win instanceof JWindow && win.getType() == Window.Type.POPUP) {
win.setFocusableWindowState(true);
}
pop.show();
System.out.println("Popup type: " + pop.getClass().getName());
System.out.println("Can get focus? " + field.requestFocusInWindow());
}
}
});
frm.add(p);
frm.setSize(500, 300);
frm.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frm.setLocationRelativeTo(null);
frm.setVisible(true);
}
}
Interesting: the call field.requestFocusInWindow() still returns false, but field gets focus anyway.
BTW: this solution is also better for me because in my real code I get the Popup from a JComboBox (my goal is to create JTableComboBox with a table in popup and an optional filter field on top of the table).

While scrolling using up/down arrow in JComboBox, It shouldn't update the top tile which shows selected item

I want my combobox top tile only get updated when we hit enter key, not while scrolling using up/down arrows..
Currently when I scroll using up/down arrow, the current item which is currently highlighted is getting updated in top tile of JComboBox as selected item. I need to avoid this.
Here is my code. Thanks in advance!
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class SwingControlDemo {
private JFrame mainFrame;
private JLabel headerLabel;
private JLabel statusLabel;
private JPanel controlPanel;
public SwingControlDemo() {
prepareGUI();
}
public static void main(String[] args) {
SwingControlDemo swingControlDemo = new SwingControlDemo();
swingControlDemo.showComboboxDemo();
}
private void prepareGUI() {
mainFrame = new JFrame("Java Swing Examples");
mainFrame.setSize(400, 400);
mainFrame.setLayout(new GridLayout(3, 1));
mainFrame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent windowEvent) {
System.exit(0);
}
});
headerLabel = new JLabel("", JLabel.CENTER);
statusLabel = new JLabel("", JLabel.CENTER);
statusLabel.setSize(350, 100);
controlPanel = new JPanel();
controlPanel.setLayout(new FlowLayout());
mainFrame.add(headerLabel);
mainFrame.add(controlPanel);
mainFrame.add(statusLabel);
mainFrame.setVisible(true);
}
private void showComboboxDemo() {
headerLabel.setText("Control in action: JComboBox");
final DefaultComboBoxModel fruitsName = new DefaultComboBoxModel();
fruitsName.addElement("Apple");
fruitsName.addElement("Grapes");
fruitsName.addElement("Mango");
fruitsName.addElement("Peer");
fruitsName.addElement("java");
fruitsName.addElement("Mango");
final JComboBox fruitCombo = new JComboBox(fruitsName);
fruitCombo.setSelectedIndex(0);
JScrollPane fruitListScrollPane = new JScrollPane(fruitCombo);
JButton showButton = new JButton("Show");
fruitCombo.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
if (arg0.getModifiers() == ActionEvent.MOUSE_EVENT_MASK || arg0.getModifiers() == ActionEvent.KEY_EVENT_MASK || true) {
System.out.println("arg0" + " " + arg0.getModifiers());
}
}
});
fruitCombo.addKeyListener(new KeyListener() {
#Override
public void keyTyped(KeyEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void keyReleased(KeyEvent arg0) {
// TODO Auto-generated method stub
if (arg0.getKeyCode() == KeyEvent.VK_ENTER) {
System.out.println("enter key pressed" + arg0.getKeyCode());
}
}
#Override
public void keyPressed(KeyEvent arg0) {
// TODO Auto-generated method stub
}
});
System.out.println(fruitCombo.getComponentListeners().toString());
controlPanel.add(fruitListScrollPane);
controlPanel.add(showButton);
mainFrame.setVisible(true);
}
}
There is a property you can set on the combo box to prevent the firing of events when the arrow keys are used:
comboBox.putClientProperty("JComboBox.isTableCellEditor", Boolean.TRUE);
Note: you may (or may not) need to manually close the popup when using the above property:
/*
This works on non editable combo boxes
*/
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.plaf.basic.*;
import javax.swing.text.*;
public class ComboBoxAction extends JFrame implements ActionListener
{
public ComboBoxAction()
{
JComboBox<String> comboBox = new JComboBox<String>();
comboBox.addActionListener( this );
comboBox.addItem( "Item 1" );
comboBox.addItem( "Item 2" );
comboBox.addItem( "Item 3" );
comboBox.addItem( "Item 4" );
// This prevents action events from being fired when the
// up/down arrow keys are used on the dropdown menu
comboBox.putClientProperty("JComboBox.isTableCellEditor", Boolean.TRUE);
getContentPane().add( comboBox );
getContentPane().add( new JTextField(), BorderLayout.SOUTH );
}
public void actionPerformed(ActionEvent e)
{
System.out.println( e.getModifiers() );
JComboBox comboBox = (JComboBox)e.getSource();
System.out.println( comboBox.getSelectedItem() );
// make sure popup is closed when 'isTableCellEditor' is used
// comboBox.hidePopup();
}
public static void main(String[] args)
{
ComboBoxAction frame = new ComboBoxAction();
frame.setDefaultCloseOperation( EXIT_ON_CLOSE );
frame.pack();
frame.setVisible( true );
}
}
I have found one solution using custom keybinding actions. Here is the code with those changes.
package abcd;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.plaf.basic.BasicComboPopup;
public class SwingControlDemo {
private JFrame mainFrame;
private JLabel headerLabel;
private JLabel statusLabel;
private JPanel controlPanel;
public SwingControlDemo(){
prepareGUI();
}
public static void main(String[] args){
SwingControlDemo swingControlDemo = new SwingControlDemo();
swingControlDemo.showComboboxDemo();
}
private void prepareGUI(){
mainFrame = new JFrame("Java Swing Examples");
mainFrame.setSize(400,400);
mainFrame.setLayout(new GridLayout(3, 1));
mainFrame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent windowEvent){
System.exit(0);
}
});
headerLabel = new JLabel("", JLabel.CENTER);
statusLabel = new JLabel("",JLabel.CENTER);
statusLabel.setSize(350,100);
controlPanel = new JPanel();
controlPanel.setLayout(new FlowLayout());
mainFrame.add(headerLabel);
mainFrame.add(controlPanel);
mainFrame.add(statusLabel);
mainFrame.setVisible(true);
}
private void showComboboxDemo(){
headerLabel.setText("Control in action: JComboBox");
final DefaultComboBoxModel fruitsName = new DefaultComboBoxModel();
fruitsName.addElement("Apple");
fruitsName.addElement("Grapes");
fruitsName.addElement("Mango");
fruitsName.addElement("Peer");
fruitsName.addElement("java");
fruitsName.addElement("mkm");
final JComboBox fruitCombo = new JComboBox(fruitsName);
fruitCombo.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke("DOWN"), "cDownArrow");
fruitCombo.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke("UP"), "cUpArrow");
Action customDownArrow = new AbstractAction() {
#Override
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
System.out.println("in");
JComboBox box = (JComboBox)arg0.getSource();
BasicComboPopup pop = (BasicComboPopup)box.getAccessibleContext().getAccessibleChild(0);
JList list = pop.getList();
System.out.println("next index" + " "+ (list.getSelectedIndex()+1)%box.getItemCount());
list.setSelectedIndex((list.getSelectedIndex()+1)%box.getItemCount());
}
};
Action customUpArrow = new AbstractAction() {
#Override
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
JComboBox box = (JComboBox)arg0.getSource();
BasicComboPopup pop = (BasicComboPopup)box.getAccessibleContext().getAccessibleChild(0);
JList list = pop.getList();
System.out.println("next index" + " "+ (list.getSelectedIndex()+1)%box.getItemCount());
list.setSelectedIndex(((list.getSelectedIndex()-1)%box.getItemCount()+box.getItemCount())%box.getItemCount());
}
};
fruitCombo.getActionMap().put("cDownArrow",customDownArrow);
fruitCombo.getActionMap().put("cUpArrow", customUpArrow);
fruitCombo.setSelectedIndex(0);
JScrollPane fruitListScrollPane = new JScrollPane(fruitCombo);
JButton showButton = new JButton("Show");
fruitCombo.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
if(arg0.getModifiers()==ActionEvent.MOUSE_EVENT_MASK || arg0.getModifiers()==ActionEvent.KEY_EVENT_MASK||true){
System.out.println("arg0"+" "+arg0.getModifiers());
}
}
});
/*fruitCombo.addKeyListener(new KeyListener() {
#Override
public void keyTyped(KeyEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void keyReleased(KeyEvent arg0) {
// TODO Auto-generated method stub
if(arg0.getKeyCode()==KeyEvent.VK_ENTER){
System.out.println("enter key pressed"+arg0.getKeyCode());
}
}
#Override
public void keyPressed(KeyEvent arg0) {
// TODO Auto-generated method stub
}
});*/
System.out.println(fruitCombo.getComponentListeners().toString());
controlPanel.add(fruitListScrollPane);
controlPanel.add(showButton);
mainFrame.setVisible(true);
}
}
Oracle Java has fixed this issue as it is not in par with selection using mouse.
But to enable the fix, we have to change default SWING UI property with key "ComboBox.noActionOnKeyNavigation". In the fix implemented in SourceCode they are using this property as flag. If we make it as true, JComboBox selection using keyboard wont trigger Action event.
This link will give you details of the fix. This is from OpenJDK but i have confirmed in Oracle JDK 1.8.111
http://osdir.com/ml/swing-dev-java-openjdk/2013-01/msg00029.html
So Basically we have to add this lane
UIManager.getLookAndFeelDefaults().put("ComboBox.noActionOnKeyNavigation", true);

Java: Right Click Copy Cut Paste On TextField

I've made a program which prints a value in a text field. The problem is that when a user right clicks in the text field, a menu like this won't open:
Is there a way the user can have this menu open upon right click?
This is my code:
public class A extends JFrame{
private JTextField txt1;
private JTextField txt2;
private JLabel val;
private JLabel prt;
private JButton bt1;
public A() {
getContentPane().setLayout(null);
txt1 = new JTextField();
txt1.setBounds(178, 93, 87, 28);
getContentPane().add(txt1);
txt2 = new JTextField();
txt2.setBounds(178, 148, 87, 28);
getContentPane().add(txt2);
val = new JLabel("Enter Value");
val.setBounds(84, 93, 69, 28);
getContentPane().add(val);
prt = new JLabel("Printed Value");
prt.setBounds(80, 148, 87, 28);
getContentPane().add(prt);
bt1 = new JButton("Click This");
bt1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
int n=Integer.parseInt(txt1.getText());
txt2.setText(n+"");
}
});
bt1.setBounds(178, 188, 105, 28);
getContentPane().add(bt1);
setSize(400, 399);
setResizable(false);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
setVisible(true);
}
}
Main Method:
public class Main {
public static void main(String[] args) {
A object = new A();
}
}
Read the Swing tutorial on How to Use Menus for the basics of creating a popup menu.
Then you can use the Actions provided by the DefaultEditorKit to create your popup menu.
For the "Delete" action you will need to create your own custom Action. Read the Swing tutorial on How to Use Actions for the basics. Except you would extend TextAction since it has methods that allow you to access the text component with focus so you can create reusable code.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.text.*;
public class TextFieldPopup extends JPanel
{
public TextFieldPopup()
{
JTextField textField = new JTextField(10);
add( textField );
JPopupMenu menu = new JPopupMenu();
Action cut = new DefaultEditorKit.CutAction();
cut.putValue(Action.NAME, "Cut");
cut.putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke("control X"));
menu.add( cut );
Action copy = new DefaultEditorKit.CopyAction();
copy.putValue(Action.NAME, "Copy");
copy.putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke("control C"));
menu.add( copy );
Action paste = new DefaultEditorKit.PasteAction();
paste.putValue(Action.NAME, "Paste");
paste.putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke("control V"));
menu.add( paste );
Action selectAll = new SelectAll();
menu.add( selectAll );
textField.setComponentPopupMenu( menu );
}
static class SelectAll extends TextAction
{
public SelectAll()
{
super("Select All");
putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke("control S"));
}
public void actionPerformed(ActionEvent e)
{
JTextComponent component = getFocusedComponent();
component.selectAll();
component.requestFocusInWindow();
}
}
private static void createAndShowGUI()
{
JFrame frame = new JFrame("TextFieldPopup");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add( new TextFieldPopup() );
frame.setLocationByPlatform( true );
frame.pack();
frame.setVisible( true );
}
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
createAndShowGUI();
}
});
}
}
Static class to instantly add regular popup menu to a textfield.
import javax.swing.*;
import java.awt.event.ActionEvent;
import javax.swing.undo.*;
public class JTextFieldRegularPopupMenu {
public static void addTo(JTextField txtField)
{
JPopupMenu popup = new JPopupMenu();
UndoManager undoManager = new UndoManager();
txtField.getDocument().addUndoableEditListener(undoManager);
Action undoAction = new AbstractAction("Undo") {
#Override
public void actionPerformed(ActionEvent ae) {
if (undoManager.canUndo()) {
undoManager.undo();
}
else {
System.out.println("No Undo Buffer.");
}
}
};
Action copyAction = new AbstractAction("Copy") {
#Override
public void actionPerformed(ActionEvent ae) {
txtField.copy();
}
};
Action cutAction = new AbstractAction("Cut") {
#Override
public void actionPerformed(ActionEvent ae) {
txtField.cut();
}
};
Action pasteAction = new AbstractAction("Paste") {
#Override
public void actionPerformed(ActionEvent ae) {
txtField.paste();
}
};
Action selectAllAction = new AbstractAction("Select All") {
#Override
public void actionPerformed(ActionEvent ae) {
txtField.selectAll();
}
};
cutAction.putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke("control X"));
copyAction.putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke("control C"));
pasteAction.putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke("control V"));
selectAllAction.putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke("control A"));
popup.add (undoAction);
popup.addSeparator();
popup.add (cutAction);
popup.add (copyAction);
popup.add (pasteAction);
popup.addSeparator();
popup.add (selectAllAction);
txtField.setComponentPopupMenu(popup);
}
}
Usage:
JTextFieldRegularPopupMenu.addTo(jTxtMsg);
Instantly adds popup menu to the chosen JTextFIeld.
I'd start with How to use menus and Bringing Up a Popup Menu (although I'd personally use JComponent#setComponentPopupMenu instead of a MouseListener)
Then I'd have a look at JTextField#copy, JTextField#cut and JTextField#paste

JoptionPane is showed two times when a list item is selected

When I click on an item of a JComboBox to show a JoptionPane with the text of selected item , it is showed two times. How can I desactive the item listener event?
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import javax.swing.*;
public class Combo implements ItemListener {
JFrame f;
JComboBox cb;
Combo() {
f = new JFrame("Combo ex");
String country[] = {"India", "Aus", "U.S.A", "England", "Newzeland"};
cb = new JComboBox(country);
cb.setBounds(50, 50, 90, 20);
f.add(cb);
cb.addItemListener(this);
f.setLayout(null);
f.setSize(400, 500);
f.setVisible(true);
}
public static void main(String[] args) {
new Combo();
}
#Override
public void itemStateChanged(ItemEvent e) {
if (e.getSource()==cb) {
String seleccionado=(String)cb.getSelectedItem();
JOptionPane.showMessageDialog(f, seleccionado);
}
}
}
You want to avoid overriding itemStateChanged(). Changing the state of the item within itemStateChanged causes itemStateChanged to be fired... which is why you're seeing the dialog twice. You should use an ActionListener instead.
I slightly modified your code as an example. It should show only 1 dialog box now.
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class Combo{
JFrame frame;
JComboBox cb;
Combo() {
frame = new JFrame("Combo ex");
String country[] = {"India", "Aus", "U.S.A", "England", "Newzeland"};
cb = new JComboBox(country);
cb.setBounds(50, 50, 90, 20);
cb.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent e) {
String seleccionado=(String)cb.getSelectedItem();
JOptionPane.showMessageDialog(frame, seleccionado);
}
});
frame.add(cb);
frame.setLayout(null);
frame.setSize(400, 500);
frame.setVisible(true);
}
public static void main(String[] args) {
new Combo();
}
}
Problem is, itemStateChanged() is invoked when an item has been selected or deselected by the user. In simple terms, when you select a new item, you also deselected the old item.
Try this:
if (e.getSource()==cb && e.getStateChange() == ItemEvent.SELECTED) {
//
}
getStateChange(), returns the type of state change (selected or deselected).

Categories