Simulating enter key in Swing (without using Robot) - java

So I'm trying to write a JButton that will act like an enter key when pressed. It must be able to fool a JTextField that is in focus into calling its action listeners. It can not use the robot framework, because that will make every program think enter is pressed, which is a problem.
Here is the backstory:
I have a program (written in Swing) which allows someone to enter data in many textfields and other things by hitting enter after typing in the data. It works great.
However, most people that use it are using a second program at the same time which automatically listens for an enter key and shuts off a robot (for those of you who are familiar with FIRST robotics, I'm talking about the SmartDashboard and the Driver Station). There have been quite a few complaints about this. People want to enter data without disabling the robot. As it turns out, the SmartDashboard (the program people want to hit enter on) allows custom swing components to be run along with it.

not entirely sure if I understand your requirement correctly (will delete this if not) ...
You can manually dispatch an event to whatever component you want to address. In the case of wanting to dispatch to the focusOwner
find the focusOwner by querying the KeyboardFocusManager
create a keyEvent with the focusOwner as sender
dispatch that event to the focusOwner
Something like:
Action action = new AbstractAction("fake enter") {
#Override
public void actionPerformed(ActionEvent e) {
KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager();
Component comp = manager.getFocusOwner();
KeyEvent event = new KeyEvent(comp,
KeyEvent.KEY_PRESSED, System.currentTimeMillis(), 0,
KeyEvent.VK_ENTER, KeyEvent.CHAR_UNDEFINED);
comp.dispatchKeyEvent(event);
}
};
JButton button = new JButton(action);
button.setFocusable(false);
Action textAction = new AbstractAction("text") {
#Override
public void actionPerformed(ActionEvent e) {
LOG.info("I'm the text action" + ((Component) e.getSource()).getName());
}
};
JComponent comp = Box.createVerticalBox();
for (int i = 0; i < 5; i++) {
JTextField field = new JTextField(20);
field.setName(": " + i);
field.setAction(textAction);
comp.add(field);
}
comp.add(button);
Edit
added some lines for actually playing with it (#Joe commented it's not working). Clicking the button triggers the action of the focused textField (here simply prints out the field's name) Local context is vista and jdk6u27.

You might try getRootPane().setDefaultButton() on the frame. There's an example here.

Grabbing the element with the focus and manually dispatching an enter event didn't quite work, but because I just wanted to effect various JTextField, I came up with a similar solution:
addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
Component focusOwner = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner();
if (focusOwner instanceof JTextField) {
((JTextField) focusOwner).postActionEvent();
}
}
});
Thanks for pointing me in the right direction.

Related

Java ActionListener issues

I created a frame. within the frame there is a combobox.
I am trying that each option from the combobox will create something else (JCheckBox,JRadioButton).
comboBox.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
String selection = comboBox.getSelectedItem().toString();
label3.setText(input[comboBox.getSelectedIndex()]);
//panel_mid.removeAll();
if(comboBox.getSelectedItem().toString().equals("Pilot")){
panel_mid.removeAll();
panel_mid.add(label3,BorderLayout.WEST);
panel_mid.add(text_bottom);
panel_mid.setBorder(new TitledBorder(comboBox.getSelectedItem().toString() + " options"));
panel_mid.add(jchkCaptain);
}
if(comboBox.getSelectedItem().toString().equals("Host")){
panel_mid.removeAll();
panel_mid.add(label3,BorderLayout.WEST);
panel_mid.add(text_bottom);
panel_mid.setBorder(new TitledBorder(comboBox.getSelectedItem().toString() + " options"));
panel_mid.add(regular = new JRadioButton("Regular"));
panel_mid.add(bachir = new JRadioButton("Bachir"));
panel_mid.add(calcelan = new JRadioButton("Calcelan"));
}
if(comboBox.getSelectedItem().toString().equals("Office")){
panel_mid.removeAll();
panel_mid.add(label3,BorderLayout.WEST);
panel_mid.add(text_bottom);
panel_mid.setBorder(new TitledBorder(comboBox.getSelectedItem().toString() + " options"));
}
}
});
when picked Pilot only JCheckBox shuold appear.
when picked Host only JRadioButton shuold appear.
when picked Office nothing shuold appear.
the problem is when i pick host and then pilot and then host it doesnt show the JRadioButton.
thanks for help.
you have to tell the LayoutManager something is/are changed, LayoutManager haven't any notifier about, you have to notify programatically about this changes
use container.revalidate() and container.repaint(variable for JPanels in your case) as last code line, only one time ,after all changes to the already visible Swing GUI are done
use CardLayout for to switch between views (JPanels in your case)

Problems with KeyEvent

I have a panel just with a Jtextfield that only accept numbers. So, when I press enter will load a user profile. this is just to see his profile.
What I want: When I press ENTER again all the profile will be cleared, and when I press the numbers and press ENTER again and load the profile again and again...
My problem: I pressed enter and the profile is cleared (Ok all fine), but when I enter the number and press the ENTER, The numbers are cleared and nothing happens, it is like a loop in matriculaTxt.addKeyListener(new KeyAdapter() { ... }
Sorry for my bad English.
private void matriculaTxtActionPerformed(java.awt.event.ActionEvent evt)
{
String matricula = matriculaTxt.getText().trim();
if (!matricula.matches("[0-9]+")) {
matriculaTxt.setText("");
} else {
fc = new FrequenciaController();
matriculaTxt.setEditable(false);
matriculaTxt.requestFocus();
fc.checkinManual(Integer.parseInt(matricula));
}
// the problem is here.
matriculaTxt.addKeyListener(new KeyAdapter() {
public void keyPressed(KeyEvent evt) {
if (evt.getKeyCode() == KeyEvent.VK_ENTER) {
nomeTxt.setText("");
statusTxt.setText("");
imageLb.setIcon(null);
acessoLabel.setText("");
matriculaTxt.setText("");
observacaoTxt.setText("");
System.err.println("ENTER");
PendenciasTableModel ptm = new PendenciasTableModel();// vazio
pendenciasTabela.setModel(ptm);
matriculaTxt.setEditable(true);
matriculaTxt.requestFocus();
}
}
});
}
What I wanted to do was simple. The user types in the text field their numbers, pressing ENTER: their data are loaded. requestFocus() into the text field and it will not be editable anymore, because when I press Enter again the field will be editable but everything will be deleted, and so on.
First off, you should never use a KeyListener for this sort of thing. Consider instead using either a JFormattedTextField or using a DocumentFilter to prevent non-numeric entry. Next, you should use an ActionLIstener to have the JTextField accept and react to the user's pressing the Enter key.
Edit
You state:
my exact requirements is, when i press ENTER again all data will be cleaned for a new data be inserted.
Why not simply have in your JTextField's ActionLIstener:
#Override
public void actionPerformed(ActionEvent e) {
// get the text
JTextComponent textComp = (JTextComponent) e.getSource();
String text = textComp.getText();
// do what you want with text here
// clear the text
textComp.setText("");
}
Again, you should not use a KeyListener for any of this stuff.
Edit 2
If you want a multi-state action listener, one that reacts differently depending on the state of the program, then give it some if blocks to allow it to react to the state of the JTextField. If the field is empty, do one thing, if it has numbers, do another, if it has text, show a warning and clear it:
#Override
public void actionPerformed(ActionEvent e) {
// get the text
JTextComponent textComp = (JTextComponent) e.getSource();
String text = textComp.getText().trim(); // trim it to rid it of white space
if (text.isEmpty()) {
// code to show a profile
return; // to exit this method
}
// if we're here, the field is not empty
if (!text.matches("[0-9]+")) {
// show a warning message here
} else {
// numeric only data present
// do action for this state
}
// clear the text
textComp.setText("");
}
The key again is to not use a KeyListener, but rather to "listen" for the enter key press with the ActionListener only, but to react differently depending on the state of the program, here likely being depending on what content is present in the JTextField.
I think that your problem that the KeyListener it'll not trigger, it will not execute the code inside it, because whenever you press ENTER it will trigger the matriculaTxtActionPerformed then declared the KeyLister, so the ENTER will effect it.

disable mouseEvent for a specific JButton in a group of JButtons

The flow of the program is like this : Image from 1st set of buttons (leftButtonArea) is dragged to the 2nd set of buttons (rightButtonArea).
Each image has a unique name via setName(). The name of the image that was dragged over will be compared with the name of the button which it is dragged to.
If the name matches, I wish to disable that particular button from reacting to any hover event.
.setHoverEnabled(false) doesn't work =/
A similar SO thread regarding the disabling of event listeners, but it seems like the solutions such a using a glass pane are for whole components ?
link
Edit:
Somehow this works, but I am not sure of any side effects from this method
source.removeMouseListener(source.getMouseListeners()[1]);
Edit2:
Found something interesting.. This could be the reason why disabled buttons still reacts to mouseEvents.
"low-level: Component, Container, Focus, Key, Mouse, Paint, Window
semantic: Action, Adjustment, Item, Text
Only semantic events are affected by disabling any component. That is because they are directly handled by the component itself which is aware that it is enabled or not.
Low level events can't be affected by disabling. If you stop to think about this when you disabled your label was it still visible. If it was then the paint event must have happened. Low level events will always happen and it is up to your handlers to query the component if it is enabled or not."
// 1st set of 4 buttons
for(int a=0; a<4; a++){
leftButtonArea[a] = new JleftButtonArea(new ImageIcon(image));
TransferHandler transfer = new TransferHandler("icon");
leftButtonArea[a].setTransferHandler(transfer);
leftButtonArea[a].addMouseListener(new MouseAdapter(){
public void mousePressed(MouseEvent e){
JleftButtonArea leftButtonArea = (JleftButtonArea)e.getSource();
TransferHandler handle = leftButtonArea.getTransferHandler();
handle.exportAsDrag(leftButtonArea, e, TransferHandler.COPY);
// get unique name for the image that is dragged
// to rightButtonArea
name1 = e.getComponent().getName();
}
});
}
// creates 2nd set of 4 buttons
for(int b=0; b<4; b++){
rightleftButtonAreaArea[b] = new JleftButtonArea();
// <---- creates unique name for each leftButtonArea ----->
cc2 += 1;
id2+="a"+cc2;
rightleftButtonAreaArea[b].setName(id2);
// <---- creates unique name for each leftButtonArea ----->
TransferHandler transfer1 = new TransferHandler("icon");
rightleftButtonAreaArea[b].setTransferHandler(transfer1);
rightleftButtonAreaArea[b].addMouseListener(new MouseAdapter(){
#Override
public void mouseExited(MouseEvent me){
JleftButtonArea source = (JleftButtonArea)me.getSource();
try{
// compare unique name of image and the button in rightButtonArea
// if they are the same, disable hover for the button
if( name1.equals(source.getName())){
// this doesn't work
source.getName().setHoverEnabled(false);
// Somehow this works, but I am not sure of any side effects from this
source.removeMouseListener(source.getMouseListeners()[1]);
}
else{
source.setIcon(null);
}
}
catch (NullPointerException e)
{
}
}
});
}
for Buttons JComponents are MouseEvent are implemented in the ButtonModel
use implemented methods for Icon in the JButton API
examples JButton & Icon, JButton & ButtonModel
try
button.setRolloverEnabled(false);

Java Editable JCombobox Keylistener event for Enter key

I have editable JCombobox and I added keylistener for combobox editor component.
When user press 'Enter key' and if there is no text on the editable combobox I need to display message box using JOptinoPane. I have done necessary code in keyrelease event and it displays message as expected.
Problem is, when we get message box and if user press enter key on 'OK' button of JOptionPane, combobox editor keyevent fires again. Because of this, when user press Enter key on message box, JoptionPane displays continuously.
Any idea how to solve this?
Note that I can't use Action listener for this.
Please check if this code helps you!!!
JFrame frame = new JFrame("Welcome!!");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JComboBox cmb = new JComboBox();
cmb.setEditable(true);
cmb.getEditor().getEditorComponent().addKeyListener(new KeyAdapter() {
#Override
public void keyReleased(KeyEvent event) {
if (event.getKeyChar() == KeyEvent.VK_ENTER) {
if (((JTextComponent) ((JComboBox) ((Component) event
.getSource()).getParent()).getEditor()
.getEditorComponent()).getText().isEmpty())
System.out.println("please dont make me blank");
}
}
});
frame.add(cmb);
frame.setLocationRelativeTo(null);
frame.setSize(300, 50);
frame.setVisible(true);
Most people find it difficult because of this casting.
We need to add a key listener on the component that the combo box is using to service the editing.
JTextComponent editor = (JTextComponent) urCombo.getEditor().getEditorComponent();
editor.addKeyListener(new KeyAdapter() {
public void keyReleased(KeyEvent evt) {
// your code
}
});
Hope this code helps.
Note that I can't use Action listener for this.
this doesn't make me any sence, then to use ItemListener
Any idea how to solve this?
never to use KeyListener for Swing JComponents, use (Note that I can't use Action listener for this.) KeyBindings instead,
notice ENTER key is implemented for JComboBox in API by default, have to override this action from ENTER key pressed
One option would be to replace the KeySelectionManager interface with your own. You want to replace the JComboBox.KeySelectionManager as it is responsible for taking the inputted char and returns the row number (as an int) which should be selected.
Please check the event ascii code by ev.getkeycode() and check if it is a number or character. If it is neither a number nor a character do nothing.
If it is what you want then do the process.
If you are using Netbeans then right click on your combobox and select customize code.
add following lines of code
JTextComponent editor = (JTextComponent) Code.getEditor().getEditorComponent();
editor.addKeyListener(new KeyAdapter() {
public void keyReleased(KeyEvent evt) {
if(evt.getKeyCode()==10)
//do your coding here.
}
});

How can I enable a text field when a button is clicked?

before I start, I'm a beginner programmer.
How can I enable a text field when a button is clicked.
I have two frames, one that has the JFields and the other for the exception.
When the exception occurs > setEditable(false)
but what statement should I make to enable the JFields once the user click on okay button -that i've made in the exception-?
I've tried to add static boolean to exception frame, and inside the action performed of this class I initialized that boolean to true.
in the other class, I added an if statment, if that boolean is true, then setEditable(true)
-========-
The point of this program, that when the exception occurs the user cannot enter anything in the fields until he closes the exception window.
I wish you'd help me.
With all love, programmers.
The code of action performed for THE EXCEPTION WINDOW FRAME ( having Okay button. )
public void actionPerformed(ActionEvent e){
{
allow=true; //static boolean
Container TheFrame = OKButton.getParent();
do TheFrame = TheFrame.getParent();
while (!(TheFrame instanceof JFrame));
((JFrame) TheFrame).dispose();
}
The code of action performed for THE MAIN PROGRAM (having three fields, an exception will occur once the user enters non digits )
I added some comments to clarify.
public void actionPerformed(ActionEvent event) {
try{
r =Double.parseDouble(RField.getText());
s=Double.parseDouble(SField.getText());
h=Double.parseDouble(HField.getText());
Cone C = new Cone(r,s,h);//class cone
if (event.getSource() instanceof JButton) {
JButton clickedButton = (JButton) event.getSource();
if (clickedButton == VolumeButton) {
Result.append("VOLUME = "+C.volume()+ "\n");
ifV= true;//this's for clearing the fields for new entries.
}
if (clickedButton == AreaButton) {
Result.append("SURFACE AREA = "+C.surfaceArea()+ "\n");
ifA= true;//this's for clearing the fields for new entries.
}
if(ifA&&ifV){ // clearing the fields for new entries.
SField.setText(CLEAR);
HField.setText(CLEAR);
RField.setText(CLEAR);
ifV=false; ifA= false;}
}
SList.addShape(C);
}
catch(NumberFormatException e){
//Object of type "Exception__" already created
Ex.setVisible(true);//class "Exception__" is the one i've made for Exception window
SField.setText(CLEAR);
HField.setText(CLEAR);
RField.setText(CLEAR);
SField.setEditable(false);
HField.setEditable(false);
RField.setEditable(false);
}/*here, if the user clicked on -that okay in Exception window-
and variable allow initialized to "true" those statements should extend. I guess?
- everything worked correctly except for this ?*/
if(Ex.allow){
SField.setEditable(true);
HField.setEditable(true);
RField.setEditable(true); }
}
THANK YOU ALL IT FINALLY WORKED.
I added
Ex.allow(SField,HField,RField);
to the catch.
and added this method in class Exception__:
public void allow(JTextField js,JTextField jh,JTextField jr){
HField =jh;
SField =js;
RField =jr;
}
finally, to the action performed of class Exception__:
SField.setEditable(true);
HField.setEditable(true);
RField.setEditable(true);
WOHOOOO. It feels so awesome lol. Thanks all. should I delete my question or leave it for others who might face the same problem as mine? :P
Your question needs a lot more detail. But if all you want to to show an 'exception window' and allow the user to do anything else only after she dismisses this window, I think all you need is a MessageDialog:
See JOptionPane
If you need more details to be displayed you can create your own modal JDialog.
See How to Make Dialogs
Make the text field hiden by writing:
jTextfield.setVisible(fasle);
in the constructor of your form code. than use the button event " Action -> Action Performed " and write the code:
jTextfield.setVisible(true);
and thus your text field will be visible only after the button will be clicked.

Categories

Resources